diff --git a/,gitignore b/,gitignore
deleted file mode 100644
index 723ef36f4e4f32c4560383aa5987c575a30c6535..0000000000000000000000000000000000000000
--- a/,gitignore
+++ /dev/null
@@ -1 +0,0 @@
-.idea
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..a7756adf045f8a22dd9146f18a503e08c7c0afe2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+.idea
+/node_modules/**/*
\ No newline at end of file
diff --git a/clients/clients/clients.ts b/clients/clients/clients.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f7ac293415017268d506aed4fa2484fe060caccc
--- /dev/null
+++ b/clients/clients/clients.ts
@@ -0,0 +1,948 @@
+/* eslint-disable */
+import { Empty } from "../google/protobuf/empty";
+import * as _m0 from "protobufjs/minimal";
+
+export interface Client {
+  /** Внутренний идентификатор клиента внутри системы */
+  id: string;
+  /** Идентификатор пространства */
+  spaceId: string;
+  /** Имя приложения (обязательное поле) */
+  name: string;
+  /** Описание клиента, назначение */
+  description: string;
+  /** Приложение отключено и не может авторизоваться */
+  disabled?: boolean | undefined;
+  roleId: string;
+  oauth?: Client_OAuth;
+  tls?: Client_TLS;
+  apiKey?: Client_APIKey;
+}
+
+export interface Client_OAuth {
+  /** Идентификатор клиента выданные IdP сервером, используется для идентификации клиента */
+  clientId: string;
+  /** Сервис который используется для авторизации клиента */
+  authId: string;
+  /** URL для получения/обновления access token клиента (опционально) */
+  tokenUrl: string;
+  /** Секретный Ключ клиента, используется для идентификации клиента (опционально) */
+  clientSecret: string;
+}
+
+export interface Client_APIKey {
+  key: string;
+  rotate: boolean;
+}
+
+export interface Client_TLS {
+  subject: string;
+}
+
+export interface CreateRequest {
+  client?: Client;
+}
+
+export interface CreateResponse {
+  created?: Client;
+}
+
+export interface GetRequest {
+  spaceId: string;
+  id: string;
+}
+
+export interface GetResponse {
+  client?: Client;
+}
+
+export interface GetByRequest {
+  spaceId: string;
+  oauthClientId: string;
+  tlsSubject: string;
+  apiKey: string;
+}
+
+export interface GetByResponse {
+  client?: Client;
+}
+
+export interface UpdateRequest {
+  client?: Client;
+}
+
+export interface ListRequest {
+  spaceId: string;
+}
+
+export interface ListResponse {
+  clients: Client[];
+}
+
+export interface DeleteRequest {
+  spaceId: string;
+  id: string;
+}
+
+export interface EnableRequest {
+  spaceId: string;
+  id: string;
+  enable: boolean;
+}
+
+function createBaseClient(): Client {
+  return {
+    id: "",
+    spaceId: "",
+    name: "",
+    description: "",
+    disabled: undefined,
+    roleId: "",
+    oauth: undefined,
+    tls: undefined,
+    apiKey: undefined,
+  };
+}
+
+export const Client = {
+  encode(
+    message: Client,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.id !== "") {
+      writer.uint32(10).string(message.id);
+    }
+    if (message.spaceId !== "") {
+      writer.uint32(18).string(message.spaceId);
+    }
+    if (message.name !== "") {
+      writer.uint32(26).string(message.name);
+    }
+    if (message.description !== "") {
+      writer.uint32(50).string(message.description);
+    }
+    if (message.disabled !== undefined) {
+      writer.uint32(56).bool(message.disabled);
+    }
+    if (message.roleId !== "") {
+      writer.uint32(66).string(message.roleId);
+    }
+    if (message.oauth !== undefined) {
+      Client_OAuth.encode(message.oauth, writer.uint32(82).fork()).ldelim();
+    }
+    if (message.tls !== undefined) {
+      Client_TLS.encode(message.tls, writer.uint32(90).fork()).ldelim();
+    }
+    if (message.apiKey !== undefined) {
+      Client_APIKey.encode(message.apiKey, writer.uint32(98).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Client {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseClient();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.id = reader.string();
+          break;
+        case 2:
+          message.spaceId = reader.string();
+          break;
+        case 3:
+          message.name = reader.string();
+          break;
+        case 6:
+          message.description = reader.string();
+          break;
+        case 7:
+          message.disabled = reader.bool();
+          break;
+        case 8:
+          message.roleId = reader.string();
+          break;
+        case 10:
+          message.oauth = Client_OAuth.decode(reader, reader.uint32());
+          break;
+        case 11:
+          message.tls = Client_TLS.decode(reader, reader.uint32());
+          break;
+        case 12:
+          message.apiKey = Client_APIKey.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Client>): Client {
+    const message = createBaseClient();
+    message.id = object.id ?? "";
+    message.spaceId = object.spaceId ?? "";
+    message.name = object.name ?? "";
+    message.description = object.description ?? "";
+    message.disabled = object.disabled ?? undefined;
+    message.roleId = object.roleId ?? "";
+    message.oauth =
+      object.oauth !== undefined && object.oauth !== null
+        ? Client_OAuth.fromPartial(object.oauth)
+        : undefined;
+    message.tls =
+      object.tls !== undefined && object.tls !== null
+        ? Client_TLS.fromPartial(object.tls)
+        : undefined;
+    message.apiKey =
+      object.apiKey !== undefined && object.apiKey !== null
+        ? Client_APIKey.fromPartial(object.apiKey)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseClient_OAuth(): Client_OAuth {
+  return { clientId: "", authId: "", tokenUrl: "", clientSecret: "" };
+}
+
+export const Client_OAuth = {
+  encode(
+    message: Client_OAuth,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.clientId !== "") {
+      writer.uint32(34).string(message.clientId);
+    }
+    if (message.authId !== "") {
+      writer.uint32(42).string(message.authId);
+    }
+    if (message.tokenUrl !== "") {
+      writer.uint32(82).string(message.tokenUrl);
+    }
+    if (message.clientSecret !== "") {
+      writer.uint32(90).string(message.clientSecret);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Client_OAuth {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseClient_OAuth();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 4:
+          message.clientId = reader.string();
+          break;
+        case 5:
+          message.authId = reader.string();
+          break;
+        case 10:
+          message.tokenUrl = reader.string();
+          break;
+        case 11:
+          message.clientSecret = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Client_OAuth>): Client_OAuth {
+    const message = createBaseClient_OAuth();
+    message.clientId = object.clientId ?? "";
+    message.authId = object.authId ?? "";
+    message.tokenUrl = object.tokenUrl ?? "";
+    message.clientSecret = object.clientSecret ?? "";
+    return message;
+  },
+};
+
+function createBaseClient_APIKey(): Client_APIKey {
+  return { key: "", rotate: false };
+}
+
+export const Client_APIKey = {
+  encode(
+    message: Client_APIKey,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.key !== "") {
+      writer.uint32(10).string(message.key);
+    }
+    if (message.rotate === true) {
+      writer.uint32(16).bool(message.rotate);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Client_APIKey {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseClient_APIKey();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.key = reader.string();
+          break;
+        case 2:
+          message.rotate = reader.bool();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Client_APIKey>): Client_APIKey {
+    const message = createBaseClient_APIKey();
+    message.key = object.key ?? "";
+    message.rotate = object.rotate ?? false;
+    return message;
+  },
+};
+
+function createBaseClient_TLS(): Client_TLS {
+  return { subject: "" };
+}
+
+export const Client_TLS = {
+  encode(
+    message: Client_TLS,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.subject !== "") {
+      writer.uint32(10).string(message.subject);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Client_TLS {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseClient_TLS();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.subject = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Client_TLS>): Client_TLS {
+    const message = createBaseClient_TLS();
+    message.subject = object.subject ?? "";
+    return message;
+  },
+};
+
+function createBaseCreateRequest(): CreateRequest {
+  return { client: undefined };
+}
+
+export const CreateRequest = {
+  encode(
+    message: CreateRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.client !== undefined) {
+      Client.encode(message.client, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CreateRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCreateRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.client = Client.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CreateRequest>): CreateRequest {
+    const message = createBaseCreateRequest();
+    message.client =
+      object.client !== undefined && object.client !== null
+        ? Client.fromPartial(object.client)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseCreateResponse(): CreateResponse {
+  return { created: undefined };
+}
+
+export const CreateResponse = {
+  encode(
+    message: CreateResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.created !== undefined) {
+      Client.encode(message.created, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CreateResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCreateResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.created = Client.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CreateResponse>): CreateResponse {
+    const message = createBaseCreateResponse();
+    message.created =
+      object.created !== undefined && object.created !== null
+        ? Client.fromPartial(object.created)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseGetRequest(): GetRequest {
+  return { spaceId: "", id: "" };
+}
+
+export const GetRequest = {
+  encode(
+    message: GetRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.id !== "") {
+      writer.uint32(18).string(message.id);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.id = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetRequest>): GetRequest {
+    const message = createBaseGetRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.id = object.id ?? "";
+    return message;
+  },
+};
+
+function createBaseGetResponse(): GetResponse {
+  return { client: undefined };
+}
+
+export const GetResponse = {
+  encode(
+    message: GetResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.client !== undefined) {
+      Client.encode(message.client, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.client = Client.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetResponse>): GetResponse {
+    const message = createBaseGetResponse();
+    message.client =
+      object.client !== undefined && object.client !== null
+        ? Client.fromPartial(object.client)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseGetByRequest(): GetByRequest {
+  return { spaceId: "", oauthClientId: "", tlsSubject: "", apiKey: "" };
+}
+
+export const GetByRequest = {
+  encode(
+    message: GetByRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.oauthClientId !== "") {
+      writer.uint32(18).string(message.oauthClientId);
+    }
+    if (message.tlsSubject !== "") {
+      writer.uint32(26).string(message.tlsSubject);
+    }
+    if (message.apiKey !== "") {
+      writer.uint32(34).string(message.apiKey);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetByRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetByRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.oauthClientId = reader.string();
+          break;
+        case 3:
+          message.tlsSubject = reader.string();
+          break;
+        case 4:
+          message.apiKey = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetByRequest>): GetByRequest {
+    const message = createBaseGetByRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.oauthClientId = object.oauthClientId ?? "";
+    message.tlsSubject = object.tlsSubject ?? "";
+    message.apiKey = object.apiKey ?? "";
+    return message;
+  },
+};
+
+function createBaseGetByResponse(): GetByResponse {
+  return { client: undefined };
+}
+
+export const GetByResponse = {
+  encode(
+    message: GetByResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.client !== undefined) {
+      Client.encode(message.client, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetByResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetByResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.client = Client.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetByResponse>): GetByResponse {
+    const message = createBaseGetByResponse();
+    message.client =
+      object.client !== undefined && object.client !== null
+        ? Client.fromPartial(object.client)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseUpdateRequest(): UpdateRequest {
+  return { client: undefined };
+}
+
+export const UpdateRequest = {
+  encode(
+    message: UpdateRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.client !== undefined) {
+      Client.encode(message.client, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UpdateRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUpdateRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.client = Client.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UpdateRequest>): UpdateRequest {
+    const message = createBaseUpdateRequest();
+    message.client =
+      object.client !== undefined && object.client !== null
+        ? Client.fromPartial(object.client)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseListRequest(): ListRequest {
+  return { spaceId: "" };
+}
+
+export const ListRequest = {
+  encode(
+    message: ListRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ListRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListRequest>): ListRequest {
+    const message = createBaseListRequest();
+    message.spaceId = object.spaceId ?? "";
+    return message;
+  },
+};
+
+function createBaseListResponse(): ListResponse {
+  return { clients: [] };
+}
+
+export const ListResponse = {
+  encode(
+    message: ListResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.clients) {
+      Client.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ListResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.clients.push(Client.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListResponse>): ListResponse {
+    const message = createBaseListResponse();
+    message.clients = object.clients?.map((e) => Client.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseDeleteRequest(): DeleteRequest {
+  return { spaceId: "", id: "" };
+}
+
+export const DeleteRequest = {
+  encode(
+    message: DeleteRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.id !== "") {
+      writer.uint32(18).string(message.id);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): DeleteRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseDeleteRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.id = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<DeleteRequest>): DeleteRequest {
+    const message = createBaseDeleteRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.id = object.id ?? "";
+    return message;
+  },
+};
+
+function createBaseEnableRequest(): EnableRequest {
+  return { spaceId: "", id: "", enable: false };
+}
+
+export const EnableRequest = {
+  encode(
+    message: EnableRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.id !== "") {
+      writer.uint32(18).string(message.id);
+    }
+    if (message.enable === true) {
+      writer.uint32(24).bool(message.enable);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): EnableRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseEnableRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.id = reader.string();
+          break;
+        case 3:
+          message.enable = reader.bool();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<EnableRequest>): EnableRequest {
+    const message = createBaseEnableRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.id = object.id ?? "";
+    message.enable = object.enable ?? false;
+    return message;
+  },
+};
+
+export type ClientsDefinition = typeof ClientsDefinition;
+export const ClientsDefinition = {
+  name: "Clients",
+  fullName: "content.clients.Clients",
+  methods: {
+    /** Create - создает клиента (приложение) для работы с API */
+    create: {
+      name: "Create",
+      requestType: CreateRequest,
+      requestStream: false,
+      responseType: CreateResponse,
+      responseStream: false,
+      options: {},
+    },
+    /** Get - возвращает клиента по id */
+    get: {
+      name: "Get",
+      requestType: GetRequest,
+      requestStream: false,
+      responseType: GetResponse,
+      responseStream: false,
+      options: {},
+    },
+    /** GetByClientID - возвращает клиента по clientId системы авторизации */
+    getBy: {
+      name: "GetBy",
+      requestType: GetByRequest,
+      requestStream: false,
+      responseType: GetByResponse,
+      responseStream: false,
+      options: {},
+    },
+    /** Update - обновляет параметры клиента */
+    update: {
+      name: "Update",
+      requestType: UpdateRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    /** List - возвращает список клиентов созданных в пространстве */
+    list: {
+      name: "List",
+      requestType: ListRequest,
+      requestStream: false,
+      responseType: ListResponse,
+      responseStream: false,
+      options: {},
+    },
+    /** Delete - удаляет указанного клиента из пространстве */
+    delete: {
+      name: "Delete",
+      requestType: DeleteRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    /** Enable - активирует/деактивирует клиента. Клиент не сможет обращаться к API платформы */
+    enable: {
+      name: "Enable",
+      requestType: EnableRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+  },
+} as const;
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
diff --git a/clients/clients/index.d.ts b/clients/clients/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..33f039c35508b7c1243431ce39194e6a155d5c29
--- /dev/null
+++ b/clients/clients/index.d.ts
@@ -0,0 +1,2 @@
+export * from './clients';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/clients/index.d.ts.map b/clients/clients/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..14874de52675a779161f9283e8c8ca83f8bf4ff0
--- /dev/null
+++ b/clients/clients/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA"}
\ No newline at end of file
diff --git a/clients/clients/index.js b/clients/clients/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..985b9c95a7974bbbd96fc5d30ca30c4cde8ab444
--- /dev/null
+++ b/clients/clients/index.js
@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./clients"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/clients/index.js.map b/clients/clients/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..c4db403c06de7ffa79f19965575626b77eace5a4
--- /dev/null
+++ b/clients/clients/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAAyB"}
\ No newline at end of file
diff --git a/clients/collaborators/collaborators.ts b/clients/collaborators/collaborators.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1ec070d577e633e6b532978503f183fc7663671a
--- /dev/null
+++ b/clients/collaborators/collaborators.ts
@@ -0,0 +1,469 @@
+/* eslint-disable */
+import { Collaborator } from "../common/common";
+import { Empty } from "../google/protobuf/empty";
+import * as _m0 from "protobufjs/minimal";
+
+export interface SetRequest {
+  spaceId: string;
+  subject: string;
+  role: string;
+}
+
+export interface GetRequest {
+  spaceId: string;
+  subject: string;
+}
+
+export interface GetResponse {
+  role: string;
+}
+
+export interface RemoveRequest {
+  spaceId: string;
+  subject: string;
+}
+
+export interface ListCollaboratorsRequest {
+  spaceId: string;
+}
+
+export interface ListCollaboratorsResponse {
+  collaborators: Collaborator[];
+}
+
+export interface ListSpacesRequest {
+  subject: string;
+}
+
+export interface ListSpacesResponse {
+  spaces: Collaborator[];
+}
+
+function createBaseSetRequest(): SetRequest {
+  return { spaceId: "", subject: "", role: "" };
+}
+
+export const SetRequest = {
+  encode(
+    message: SetRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.subject !== "") {
+      writer.uint32(18).string(message.subject);
+    }
+    if (message.role !== "") {
+      writer.uint32(26).string(message.role);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): SetRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseSetRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.subject = reader.string();
+          break;
+        case 3:
+          message.role = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<SetRequest>): SetRequest {
+    const message = createBaseSetRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.subject = object.subject ?? "";
+    message.role = object.role ?? "";
+    return message;
+  },
+};
+
+function createBaseGetRequest(): GetRequest {
+  return { spaceId: "", subject: "" };
+}
+
+export const GetRequest = {
+  encode(
+    message: GetRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.subject !== "") {
+      writer.uint32(18).string(message.subject);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.subject = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetRequest>): GetRequest {
+    const message = createBaseGetRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.subject = object.subject ?? "";
+    return message;
+  },
+};
+
+function createBaseGetResponse(): GetResponse {
+  return { role: "" };
+}
+
+export const GetResponse = {
+  encode(
+    message: GetResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.role !== "") {
+      writer.uint32(26).string(message.role);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 3:
+          message.role = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetResponse>): GetResponse {
+    const message = createBaseGetResponse();
+    message.role = object.role ?? "";
+    return message;
+  },
+};
+
+function createBaseRemoveRequest(): RemoveRequest {
+  return { spaceId: "", subject: "" };
+}
+
+export const RemoveRequest = {
+  encode(
+    message: RemoveRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.subject !== "") {
+      writer.uint32(18).string(message.subject);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): RemoveRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseRemoveRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.subject = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<RemoveRequest>): RemoveRequest {
+    const message = createBaseRemoveRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.subject = object.subject ?? "";
+    return message;
+  },
+};
+
+function createBaseListCollaboratorsRequest(): ListCollaboratorsRequest {
+  return { spaceId: "" };
+}
+
+export const ListCollaboratorsRequest = {
+  encode(
+    message: ListCollaboratorsRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): ListCollaboratorsRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListCollaboratorsRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<ListCollaboratorsRequest>
+  ): ListCollaboratorsRequest {
+    const message = createBaseListCollaboratorsRequest();
+    message.spaceId = object.spaceId ?? "";
+    return message;
+  },
+};
+
+function createBaseListCollaboratorsResponse(): ListCollaboratorsResponse {
+  return { collaborators: [] };
+}
+
+export const ListCollaboratorsResponse = {
+  encode(
+    message: ListCollaboratorsResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.collaborators) {
+      Collaborator.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): ListCollaboratorsResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListCollaboratorsResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.collaborators.push(
+            Collaborator.decode(reader, reader.uint32())
+          );
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<ListCollaboratorsResponse>
+  ): ListCollaboratorsResponse {
+    const message = createBaseListCollaboratorsResponse();
+    message.collaborators =
+      object.collaborators?.map((e) => Collaborator.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseListSpacesRequest(): ListSpacesRequest {
+  return { subject: "" };
+}
+
+export const ListSpacesRequest = {
+  encode(
+    message: ListSpacesRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.subject !== "") {
+      writer.uint32(10).string(message.subject);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ListSpacesRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListSpacesRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.subject = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListSpacesRequest>): ListSpacesRequest {
+    const message = createBaseListSpacesRequest();
+    message.subject = object.subject ?? "";
+    return message;
+  },
+};
+
+function createBaseListSpacesResponse(): ListSpacesResponse {
+  return { spaces: [] };
+}
+
+export const ListSpacesResponse = {
+  encode(
+    message: ListSpacesResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.spaces) {
+      Collaborator.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ListSpacesResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListSpacesResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaces.push(Collaborator.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListSpacesResponse>): ListSpacesResponse {
+    const message = createBaseListSpacesResponse();
+    message.spaces =
+      object.spaces?.map((e) => Collaborator.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+export type CollaboratorsDefinition = typeof CollaboratorsDefinition;
+export const CollaboratorsDefinition = {
+  name: "Collaborators",
+  fullName: "content.collaborators.Collaborators",
+  methods: {
+    set: {
+      name: "Set",
+      requestType: SetRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    get: {
+      name: "Get",
+      requestType: GetRequest,
+      requestStream: false,
+      responseType: GetResponse,
+      responseStream: false,
+      options: {},
+    },
+    remove: {
+      name: "Remove",
+      requestType: RemoveRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    listCollaborators: {
+      name: "ListCollaborators",
+      requestType: ListCollaboratorsRequest,
+      requestStream: false,
+      responseType: ListCollaboratorsResponse,
+      responseStream: false,
+      options: {},
+    },
+    listSpaces: {
+      name: "ListSpaces",
+      requestType: ListSpacesRequest,
+      requestStream: false,
+      responseType: ListSpacesResponse,
+      responseStream: false,
+      options: {},
+    },
+  },
+} as const;
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
diff --git a/clients/collaborators/index.d.ts b/clients/collaborators/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..069a2e11b244aff9444e2bd5f2c377ea87d37915
--- /dev/null
+++ b/clients/collaborators/index.d.ts
@@ -0,0 +1,2 @@
+export * from './collaborators';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/collaborators/index.d.ts.map b/clients/collaborators/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..af6256bd84692b57f2bad605bed20be9c33e01e8
--- /dev/null
+++ b/clients/collaborators/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA"}
\ No newline at end of file
diff --git a/clients/collaborators/index.js b/clients/collaborators/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..cb29299244885e1914b633a34cbf3800c30a842b
--- /dev/null
+++ b/clients/collaborators/index.js
@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./collaborators"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/collaborators/index.js.map b/clients/collaborators/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..77c64a5e9dd05cb19d3c871162cb64cea8a2371b
--- /dev/null
+++ b/clients/collaborators/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAA+B"}
\ No newline at end of file
diff --git a/clients/collections/collections.ts b/clients/collections/collections.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f630254c43219688889529c68184c2cd6a8057f9
--- /dev/null
+++ b/clients/collections/collections.ts
@@ -0,0 +1,1096 @@
+/* eslint-disable */
+import { Timestamp } from "../google/protobuf/timestamp";
+import { Action } from "../common/common";
+import { Empty } from "../google/protobuf/empty";
+import * as _m0 from "protobufjs/minimal";
+
+export interface Access {
+  actions: Action[];
+  hiddenFields: string[];
+  readonlyFields: string[];
+  writeonlyFields: string[];
+}
+
+export interface Collection {
+  id: string;
+  spaceId: string;
+  envId: string;
+  name: string;
+  single?: boolean | undefined;
+  system?: boolean | undefined;
+  noData?: boolean | undefined;
+  schema: string;
+  /** string feature = 8; */
+  hidden: boolean;
+  view?: Collection_View;
+  stateInfo?: Collection_StateInfo;
+  access?: Access;
+}
+
+export enum Collection_State {
+  /** NEW - коллекция создана, еще не обработана */
+  NEW = 0,
+  /** PREPARING - производится подготовка коллекции (создание индексов, копирование данных) */
+  PREPARING = 1,
+  /** READY - коллекция готова к работе */
+  READY = 2,
+  /** ERROR - при обработке коллекции произошла ошибка */
+  ERROR = 3,
+  /** CHANGED - в коллекцию внесены изменения, но  еще не были применены. Коллекция должна после перейти в состояние Preparing */
+  CHANGED = 4,
+  UNRECOGNIZED = -1,
+}
+
+export interface Collection_View {
+  spaceId: string;
+  envId: string;
+  collectionId: string;
+  filter: string;
+}
+
+export interface Collection_StateInfo {
+  state: Collection_State;
+  info: string;
+  startedAt?: Timestamp;
+}
+
+export interface CreateRequest {
+  collection?: Collection;
+}
+
+export interface CreateResponse {
+  created?: Collection;
+}
+
+export interface GetOptions {
+  disableSchemaIncludes: boolean;
+}
+
+export interface GetRequest {
+  spaceId: string;
+  envId: string;
+  collectionId: string;
+  options?: GetOptions;
+}
+
+export interface GetResponse {
+  collection?: Collection;
+}
+
+export interface ListRequest {
+  spaceId: string;
+  envId: string;
+  filter?: ListRequest_Filter;
+}
+
+export interface ListRequest_Filter {
+  excludeSystem: boolean;
+  /** bool exclude_no_data = 2; */
+  includeNoData: boolean;
+  includeHidden: boolean;
+  name: string[];
+  id: string[];
+}
+
+export interface ListResponse {
+  collections: Collection[];
+}
+
+export interface UpdateRequest {
+  collection?: Collection;
+}
+
+export interface SetSchemaRequest {
+  spaceId: string;
+  envId: string;
+  collectionId: string;
+  schema: string;
+}
+
+export interface DeleteRequest {
+  spaceId: string;
+  envId: string;
+  collectionId: string;
+}
+
+function createBaseAccess(): Access {
+  return {
+    actions: [],
+    hiddenFields: [],
+    readonlyFields: [],
+    writeonlyFields: [],
+  };
+}
+
+export const Access = {
+  encode(
+    message: Access,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    writer.uint32(10).fork();
+    for (const v of message.actions) {
+      writer.int32(v);
+    }
+    writer.ldelim();
+    for (const v of message.hiddenFields) {
+      writer.uint32(42).string(v!);
+    }
+    for (const v of message.readonlyFields) {
+      writer.uint32(50).string(v!);
+    }
+    for (const v of message.writeonlyFields) {
+      writer.uint32(58).string(v!);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Access {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseAccess();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          if ((tag & 7) === 2) {
+            const end2 = reader.uint32() + reader.pos;
+            while (reader.pos < end2) {
+              message.actions.push(reader.int32() as any);
+            }
+          } else {
+            message.actions.push(reader.int32() as any);
+          }
+          break;
+        case 5:
+          message.hiddenFields.push(reader.string());
+          break;
+        case 6:
+          message.readonlyFields.push(reader.string());
+          break;
+        case 7:
+          message.writeonlyFields.push(reader.string());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Access>): Access {
+    const message = createBaseAccess();
+    message.actions = object.actions?.map((e) => e) || [];
+    message.hiddenFields = object.hiddenFields?.map((e) => e) || [];
+    message.readonlyFields = object.readonlyFields?.map((e) => e) || [];
+    message.writeonlyFields = object.writeonlyFields?.map((e) => e) || [];
+    return message;
+  },
+};
+
+function createBaseCollection(): Collection {
+  return {
+    id: "",
+    spaceId: "",
+    envId: "",
+    name: "",
+    single: undefined,
+    system: undefined,
+    noData: undefined,
+    schema: "",
+    hidden: false,
+    view: undefined,
+    stateInfo: undefined,
+    access: undefined,
+  };
+}
+
+export const Collection = {
+  encode(
+    message: Collection,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.id !== "") {
+      writer.uint32(10).string(message.id);
+    }
+    if (message.spaceId !== "") {
+      writer.uint32(18).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(26).string(message.envId);
+    }
+    if (message.name !== "") {
+      writer.uint32(34).string(message.name);
+    }
+    if (message.single !== undefined) {
+      writer.uint32(40).bool(message.single);
+    }
+    if (message.system !== undefined) {
+      writer.uint32(48).bool(message.system);
+    }
+    if (message.noData !== undefined) {
+      writer.uint32(96).bool(message.noData);
+    }
+    if (message.schema !== "") {
+      writer.uint32(58).string(message.schema);
+    }
+    if (message.hidden === true) {
+      writer.uint32(104).bool(message.hidden);
+    }
+    if (message.view !== undefined) {
+      Collection_View.encode(message.view, writer.uint32(74).fork()).ldelim();
+    }
+    if (message.stateInfo !== undefined) {
+      Collection_StateInfo.encode(
+        message.stateInfo,
+        writer.uint32(82).fork()
+      ).ldelim();
+    }
+    if (message.access !== undefined) {
+      Access.encode(message.access, writer.uint32(162).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Collection {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCollection();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.id = reader.string();
+          break;
+        case 2:
+          message.spaceId = reader.string();
+          break;
+        case 3:
+          message.envId = reader.string();
+          break;
+        case 4:
+          message.name = reader.string();
+          break;
+        case 5:
+          message.single = reader.bool();
+          break;
+        case 6:
+          message.system = reader.bool();
+          break;
+        case 12:
+          message.noData = reader.bool();
+          break;
+        case 7:
+          message.schema = reader.string();
+          break;
+        case 13:
+          message.hidden = reader.bool();
+          break;
+        case 9:
+          message.view = Collection_View.decode(reader, reader.uint32());
+          break;
+        case 10:
+          message.stateInfo = Collection_StateInfo.decode(
+            reader,
+            reader.uint32()
+          );
+          break;
+        case 20:
+          message.access = Access.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Collection>): Collection {
+    const message = createBaseCollection();
+    message.id = object.id ?? "";
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.name = object.name ?? "";
+    message.single = object.single ?? undefined;
+    message.system = object.system ?? undefined;
+    message.noData = object.noData ?? undefined;
+    message.schema = object.schema ?? "";
+    message.hidden = object.hidden ?? false;
+    message.view =
+      object.view !== undefined && object.view !== null
+        ? Collection_View.fromPartial(object.view)
+        : undefined;
+    message.stateInfo =
+      object.stateInfo !== undefined && object.stateInfo !== null
+        ? Collection_StateInfo.fromPartial(object.stateInfo)
+        : undefined;
+    message.access =
+      object.access !== undefined && object.access !== null
+        ? Access.fromPartial(object.access)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseCollection_View(): Collection_View {
+  return { spaceId: "", envId: "", collectionId: "", filter: "" };
+}
+
+export const Collection_View = {
+  encode(
+    message: Collection_View,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    if (message.collectionId !== "") {
+      writer.uint32(26).string(message.collectionId);
+    }
+    if (message.filter !== "") {
+      writer.uint32(34).string(message.filter);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Collection_View {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCollection_View();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        case 3:
+          message.collectionId = reader.string();
+          break;
+        case 4:
+          message.filter = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Collection_View>): Collection_View {
+    const message = createBaseCollection_View();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.collectionId = object.collectionId ?? "";
+    message.filter = object.filter ?? "";
+    return message;
+  },
+};
+
+function createBaseCollection_StateInfo(): Collection_StateInfo {
+  return { state: 0, info: "", startedAt: undefined };
+}
+
+export const Collection_StateInfo = {
+  encode(
+    message: Collection_StateInfo,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.state !== 0) {
+      writer.uint32(8).int32(message.state);
+    }
+    if (message.info !== "") {
+      writer.uint32(18).string(message.info);
+    }
+    if (message.startedAt !== undefined) {
+      Timestamp.encode(message.startedAt, writer.uint32(26).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): Collection_StateInfo {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCollection_StateInfo();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.state = reader.int32() as any;
+          break;
+        case 2:
+          message.info = reader.string();
+          break;
+        case 3:
+          message.startedAt = Timestamp.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Collection_StateInfo>): Collection_StateInfo {
+    const message = createBaseCollection_StateInfo();
+    message.state = object.state ?? 0;
+    message.info = object.info ?? "";
+    message.startedAt =
+      object.startedAt !== undefined && object.startedAt !== null
+        ? Timestamp.fromPartial(object.startedAt)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseCreateRequest(): CreateRequest {
+  return { collection: undefined };
+}
+
+export const CreateRequest = {
+  encode(
+    message: CreateRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.collection !== undefined) {
+      Collection.encode(message.collection, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CreateRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCreateRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.collection = Collection.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CreateRequest>): CreateRequest {
+    const message = createBaseCreateRequest();
+    message.collection =
+      object.collection !== undefined && object.collection !== null
+        ? Collection.fromPartial(object.collection)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseCreateResponse(): CreateResponse {
+  return { created: undefined };
+}
+
+export const CreateResponse = {
+  encode(
+    message: CreateResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.created !== undefined) {
+      Collection.encode(message.created, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CreateResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCreateResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.created = Collection.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CreateResponse>): CreateResponse {
+    const message = createBaseCreateResponse();
+    message.created =
+      object.created !== undefined && object.created !== null
+        ? Collection.fromPartial(object.created)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseGetOptions(): GetOptions {
+  return { disableSchemaIncludes: false };
+}
+
+export const GetOptions = {
+  encode(
+    message: GetOptions,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.disableSchemaIncludes === true) {
+      writer.uint32(8).bool(message.disableSchemaIncludes);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetOptions {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetOptions();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.disableSchemaIncludes = reader.bool();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetOptions>): GetOptions {
+    const message = createBaseGetOptions();
+    message.disableSchemaIncludes = object.disableSchemaIncludes ?? false;
+    return message;
+  },
+};
+
+function createBaseGetRequest(): GetRequest {
+  return { spaceId: "", envId: "", collectionId: "", options: undefined };
+}
+
+export const GetRequest = {
+  encode(
+    message: GetRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    if (message.collectionId !== "") {
+      writer.uint32(26).string(message.collectionId);
+    }
+    if (message.options !== undefined) {
+      GetOptions.encode(message.options, writer.uint32(34).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        case 3:
+          message.collectionId = reader.string();
+          break;
+        case 4:
+          message.options = GetOptions.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetRequest>): GetRequest {
+    const message = createBaseGetRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.collectionId = object.collectionId ?? "";
+    message.options =
+      object.options !== undefined && object.options !== null
+        ? GetOptions.fromPartial(object.options)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseGetResponse(): GetResponse {
+  return { collection: undefined };
+}
+
+export const GetResponse = {
+  encode(
+    message: GetResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.collection !== undefined) {
+      Collection.encode(message.collection, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.collection = Collection.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetResponse>): GetResponse {
+    const message = createBaseGetResponse();
+    message.collection =
+      object.collection !== undefined && object.collection !== null
+        ? Collection.fromPartial(object.collection)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseListRequest(): ListRequest {
+  return { spaceId: "", envId: "", filter: undefined };
+}
+
+export const ListRequest = {
+  encode(
+    message: ListRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    if (message.filter !== undefined) {
+      ListRequest_Filter.encode(
+        message.filter,
+        writer.uint32(42).fork()
+      ).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ListRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        case 5:
+          message.filter = ListRequest_Filter.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListRequest>): ListRequest {
+    const message = createBaseListRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.filter =
+      object.filter !== undefined && object.filter !== null
+        ? ListRequest_Filter.fromPartial(object.filter)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseListRequest_Filter(): ListRequest_Filter {
+  return {
+    excludeSystem: false,
+    includeNoData: false,
+    includeHidden: false,
+    name: [],
+    id: [],
+  };
+}
+
+export const ListRequest_Filter = {
+  encode(
+    message: ListRequest_Filter,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.excludeSystem === true) {
+      writer.uint32(8).bool(message.excludeSystem);
+    }
+    if (message.includeNoData === true) {
+      writer.uint32(40).bool(message.includeNoData);
+    }
+    if (message.includeHidden === true) {
+      writer.uint32(48).bool(message.includeHidden);
+    }
+    for (const v of message.name) {
+      writer.uint32(26).string(v!);
+    }
+    for (const v of message.id) {
+      writer.uint32(34).string(v!);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ListRequest_Filter {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListRequest_Filter();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.excludeSystem = reader.bool();
+          break;
+        case 5:
+          message.includeNoData = reader.bool();
+          break;
+        case 6:
+          message.includeHidden = reader.bool();
+          break;
+        case 3:
+          message.name.push(reader.string());
+          break;
+        case 4:
+          message.id.push(reader.string());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListRequest_Filter>): ListRequest_Filter {
+    const message = createBaseListRequest_Filter();
+    message.excludeSystem = object.excludeSystem ?? false;
+    message.includeNoData = object.includeNoData ?? false;
+    message.includeHidden = object.includeHidden ?? false;
+    message.name = object.name?.map((e) => e) || [];
+    message.id = object.id?.map((e) => e) || [];
+    return message;
+  },
+};
+
+function createBaseListResponse(): ListResponse {
+  return { collections: [] };
+}
+
+export const ListResponse = {
+  encode(
+    message: ListResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.collections) {
+      Collection.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ListResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.collections.push(Collection.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListResponse>): ListResponse {
+    const message = createBaseListResponse();
+    message.collections =
+      object.collections?.map((e) => Collection.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseUpdateRequest(): UpdateRequest {
+  return { collection: undefined };
+}
+
+export const UpdateRequest = {
+  encode(
+    message: UpdateRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.collection !== undefined) {
+      Collection.encode(message.collection, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UpdateRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUpdateRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.collection = Collection.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UpdateRequest>): UpdateRequest {
+    const message = createBaseUpdateRequest();
+    message.collection =
+      object.collection !== undefined && object.collection !== null
+        ? Collection.fromPartial(object.collection)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseSetSchemaRequest(): SetSchemaRequest {
+  return { spaceId: "", envId: "", collectionId: "", schema: "" };
+}
+
+export const SetSchemaRequest = {
+  encode(
+    message: SetSchemaRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    if (message.collectionId !== "") {
+      writer.uint32(26).string(message.collectionId);
+    }
+    if (message.schema !== "") {
+      writer.uint32(34).string(message.schema);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): SetSchemaRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseSetSchemaRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        case 3:
+          message.collectionId = reader.string();
+          break;
+        case 4:
+          message.schema = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<SetSchemaRequest>): SetSchemaRequest {
+    const message = createBaseSetSchemaRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.collectionId = object.collectionId ?? "";
+    message.schema = object.schema ?? "";
+    return message;
+  },
+};
+
+function createBaseDeleteRequest(): DeleteRequest {
+  return { spaceId: "", envId: "", collectionId: "" };
+}
+
+export const DeleteRequest = {
+  encode(
+    message: DeleteRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    if (message.collectionId !== "") {
+      writer.uint32(26).string(message.collectionId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): DeleteRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseDeleteRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        case 3:
+          message.collectionId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<DeleteRequest>): DeleteRequest {
+    const message = createBaseDeleteRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.collectionId = object.collectionId ?? "";
+    return message;
+  },
+};
+
+export type CollectionsDefinition = typeof CollectionsDefinition;
+export const CollectionsDefinition = {
+  name: "Collections",
+  fullName: "content.collections.Collections",
+  methods: {
+    create: {
+      name: "Create",
+      requestType: CreateRequest,
+      requestStream: false,
+      responseType: CreateResponse,
+      responseStream: false,
+      options: {},
+    },
+    get: {
+      name: "Get",
+      requestType: GetRequest,
+      requestStream: false,
+      responseType: GetResponse,
+      responseStream: false,
+      options: {},
+    },
+    list: {
+      name: "List",
+      requestType: ListRequest,
+      requestStream: false,
+      responseType: ListResponse,
+      responseStream: false,
+      options: {},
+    },
+    update: {
+      name: "Update",
+      requestType: UpdateRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    setSchema: {
+      name: "SetSchema",
+      requestType: SetSchemaRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    delete: {
+      name: "Delete",
+      requestType: DeleteRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+  },
+} as const;
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
diff --git a/clients/collections/index.d.ts b/clients/collections/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..49602851b735356323456ef903add0cc6dc1efd8
--- /dev/null
+++ b/clients/collections/index.d.ts
@@ -0,0 +1,2 @@
+export * from './collections';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/collections/index.d.ts.map b/clients/collections/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..5b507a9ad2ce48aebf1a743e716198f48cf9ad30
--- /dev/null
+++ b/clients/collections/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAA"}
\ No newline at end of file
diff --git a/clients/collections/index.js b/clients/collections/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..6dd4ffede20c6a69b01b4864bb601cd3dbdfcc5e
--- /dev/null
+++ b/clients/collections/index.js
@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./collections"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/collections/index.js.map b/clients/collections/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..64c493ecdc723183734cd145ce14a34452cc0391
--- /dev/null
+++ b/clients/collections/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA6B"}
\ No newline at end of file
diff --git a/clients/common/common.ts b/clients/common/common.ts
new file mode 100644
index 0000000000000000000000000000000000000000..709e12359d632f0a176a408ad7f330850b48d4c6
--- /dev/null
+++ b/clients/common/common.ts
@@ -0,0 +1,988 @@
+/* eslint-disable */
+import Long from "long";
+import * as _m0 from "protobufjs/minimal";
+import { Value } from "../google/protobuf/struct";
+
+export enum Access {
+  ANY = 0,
+  MINE = 1,
+  ROLE = 2,
+  UNRECOGNIZED = -1,
+}
+
+export enum Action {
+  UNKNOWN = 0,
+  CREATE = 1,
+  READ = 2,
+  UPDATE = 3,
+  DELETE = 4,
+  UNRECOGNIZED = -1,
+}
+
+export interface Error {
+  /** Код ошибки */
+  errorCode: number;
+  /** ID конкретного инцидента, ID уникальна для каждого случая. */
+  errorId: string;
+  /** ??? */
+  reason: string;
+  /** Сервис,Пакет к которому относится ошибка */
+  domain: string;
+  /** Мета-информация */
+  metadata: { [key: string]: string };
+  /** Ошибка запроса */
+  badRequest?: Error_BadRequest;
+  /** Отладочная информация */
+  debugInfo?: Error_DebugInfo;
+  /** Пользовательская информации и инструкции */
+  help?: Error_Help;
+  /** Перевод сообщения об ошибке */
+  localizedMessages: Error_LocalizedMessage[];
+}
+
+export interface Error_BadRequest {
+  errors: Error_BadRequest_FieldViolation[];
+}
+
+export interface Error_BadRequest_FieldViolation {
+  field: string;
+  description: string;
+}
+
+export interface Error_Help {
+  links: Error_Help_Link[];
+}
+
+export interface Error_Help_Link {
+  description: string;
+  url: string;
+}
+
+export interface Error_DebugInfo {
+  stackTrace: string[];
+  detail: string;
+}
+
+export interface Error_LocalizedMessage {
+  locale: string;
+  message: string;
+}
+
+export interface Error_MetadataEntry {
+  key: string;
+  value: string;
+}
+
+export interface Filter {
+  op: string;
+  field: string;
+  value?: any;
+}
+
+export interface FindOptions {
+  sort: string[];
+  pageNum: number;
+  pageSize: number;
+  fields: string[];
+  excludeFields: boolean;
+}
+
+export interface Rule {
+  collectionId: string;
+  actions: Action[];
+  access: Access;
+  hiddenFields: string[];
+  readonlyFields: string[];
+  writeonlyFields: string[];
+  readFilter: string;
+  writeFilter: string;
+}
+
+export interface Collaborator {
+  spaceId: string;
+  subject: string;
+  role: string;
+}
+
+export interface Version {
+  serverVersion: string;
+  apiVersion: string;
+  buildTime: string;
+  commit: string;
+  buildNumber: number;
+}
+
+function createBaseError(): Error {
+  return {
+    errorCode: 0,
+    errorId: "",
+    reason: "",
+    domain: "",
+    metadata: {},
+    badRequest: undefined,
+    debugInfo: undefined,
+    help: undefined,
+    localizedMessages: [],
+  };
+}
+
+export const Error = {
+  encode(message: Error, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
+    if (message.errorCode !== 0) {
+      writer.uint32(8).uint64(message.errorCode);
+    }
+    if (message.errorId !== "") {
+      writer.uint32(18).string(message.errorId);
+    }
+    if (message.reason !== "") {
+      writer.uint32(26).string(message.reason);
+    }
+    if (message.domain !== "") {
+      writer.uint32(34).string(message.domain);
+    }
+    Object.entries(message.metadata).forEach(([key, value]) => {
+      Error_MetadataEntry.encode(
+        { key: key as any, value },
+        writer.uint32(74).fork()
+      ).ldelim();
+    });
+    if (message.badRequest !== undefined) {
+      Error_BadRequest.encode(
+        message.badRequest,
+        writer.uint32(82).fork()
+      ).ldelim();
+    }
+    if (message.debugInfo !== undefined) {
+      Error_DebugInfo.encode(
+        message.debugInfo,
+        writer.uint32(90).fork()
+      ).ldelim();
+    }
+    if (message.help !== undefined) {
+      Error_Help.encode(message.help, writer.uint32(802).fork()).ldelim();
+    }
+    for (const v of message.localizedMessages) {
+      Error_LocalizedMessage.encode(v!, writer.uint32(1602).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Error {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseError();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.errorCode = longToNumber(reader.uint64() as Long);
+          break;
+        case 2:
+          message.errorId = reader.string();
+          break;
+        case 3:
+          message.reason = reader.string();
+          break;
+        case 4:
+          message.domain = reader.string();
+          break;
+        case 9:
+          const entry9 = Error_MetadataEntry.decode(reader, reader.uint32());
+          if (entry9.value !== undefined) {
+            message.metadata[entry9.key] = entry9.value;
+          }
+          break;
+        case 10:
+          message.badRequest = Error_BadRequest.decode(reader, reader.uint32());
+          break;
+        case 11:
+          message.debugInfo = Error_DebugInfo.decode(reader, reader.uint32());
+          break;
+        case 100:
+          message.help = Error_Help.decode(reader, reader.uint32());
+          break;
+        case 200:
+          message.localizedMessages.push(
+            Error_LocalizedMessage.decode(reader, reader.uint32())
+          );
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Error>): Error {
+    const message = createBaseError();
+    message.errorCode = object.errorCode ?? 0;
+    message.errorId = object.errorId ?? "";
+    message.reason = object.reason ?? "";
+    message.domain = object.domain ?? "";
+    message.metadata = Object.entries(object.metadata ?? {}).reduce<{
+      [key: string]: string;
+    }>((acc, [key, value]) => {
+      if (value !== undefined) {
+        acc[key] = String(value);
+      }
+      return acc;
+    }, {});
+    message.badRequest =
+      object.badRequest !== undefined && object.badRequest !== null
+        ? Error_BadRequest.fromPartial(object.badRequest)
+        : undefined;
+    message.debugInfo =
+      object.debugInfo !== undefined && object.debugInfo !== null
+        ? Error_DebugInfo.fromPartial(object.debugInfo)
+        : undefined;
+    message.help =
+      object.help !== undefined && object.help !== null
+        ? Error_Help.fromPartial(object.help)
+        : undefined;
+    message.localizedMessages =
+      object.localizedMessages?.map((e) =>
+        Error_LocalizedMessage.fromPartial(e)
+      ) || [];
+    return message;
+  },
+};
+
+function createBaseError_BadRequest(): Error_BadRequest {
+  return { errors: [] };
+}
+
+export const Error_BadRequest = {
+  encode(
+    message: Error_BadRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.errors) {
+      Error_BadRequest_FieldViolation.encode(
+        v!,
+        writer.uint32(10).fork()
+      ).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Error_BadRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseError_BadRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.errors.push(
+            Error_BadRequest_FieldViolation.decode(reader, reader.uint32())
+          );
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Error_BadRequest>): Error_BadRequest {
+    const message = createBaseError_BadRequest();
+    message.errors =
+      object.errors?.map((e) =>
+        Error_BadRequest_FieldViolation.fromPartial(e)
+      ) || [];
+    return message;
+  },
+};
+
+function createBaseError_BadRequest_FieldViolation(): Error_BadRequest_FieldViolation {
+  return { field: "", description: "" };
+}
+
+export const Error_BadRequest_FieldViolation = {
+  encode(
+    message: Error_BadRequest_FieldViolation,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.field !== "") {
+      writer.uint32(10).string(message.field);
+    }
+    if (message.description !== "") {
+      writer.uint32(18).string(message.description);
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): Error_BadRequest_FieldViolation {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseError_BadRequest_FieldViolation();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.field = reader.string();
+          break;
+        case 2:
+          message.description = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<Error_BadRequest_FieldViolation>
+  ): Error_BadRequest_FieldViolation {
+    const message = createBaseError_BadRequest_FieldViolation();
+    message.field = object.field ?? "";
+    message.description = object.description ?? "";
+    return message;
+  },
+};
+
+function createBaseError_Help(): Error_Help {
+  return { links: [] };
+}
+
+export const Error_Help = {
+  encode(
+    message: Error_Help,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.links) {
+      Error_Help_Link.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Error_Help {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseError_Help();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.links.push(Error_Help_Link.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Error_Help>): Error_Help {
+    const message = createBaseError_Help();
+    message.links =
+      object.links?.map((e) => Error_Help_Link.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseError_Help_Link(): Error_Help_Link {
+  return { description: "", url: "" };
+}
+
+export const Error_Help_Link = {
+  encode(
+    message: Error_Help_Link,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.description !== "") {
+      writer.uint32(10).string(message.description);
+    }
+    if (message.url !== "") {
+      writer.uint32(18).string(message.url);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Error_Help_Link {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseError_Help_Link();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.description = reader.string();
+          break;
+        case 2:
+          message.url = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Error_Help_Link>): Error_Help_Link {
+    const message = createBaseError_Help_Link();
+    message.description = object.description ?? "";
+    message.url = object.url ?? "";
+    return message;
+  },
+};
+
+function createBaseError_DebugInfo(): Error_DebugInfo {
+  return { stackTrace: [], detail: "" };
+}
+
+export const Error_DebugInfo = {
+  encode(
+    message: Error_DebugInfo,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.stackTrace) {
+      writer.uint32(10).string(v!);
+    }
+    if (message.detail !== "") {
+      writer.uint32(18).string(message.detail);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Error_DebugInfo {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseError_DebugInfo();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.stackTrace.push(reader.string());
+          break;
+        case 2:
+          message.detail = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Error_DebugInfo>): Error_DebugInfo {
+    const message = createBaseError_DebugInfo();
+    message.stackTrace = object.stackTrace?.map((e) => e) || [];
+    message.detail = object.detail ?? "";
+    return message;
+  },
+};
+
+function createBaseError_LocalizedMessage(): Error_LocalizedMessage {
+  return { locale: "", message: "" };
+}
+
+export const Error_LocalizedMessage = {
+  encode(
+    message: Error_LocalizedMessage,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.locale !== "") {
+      writer.uint32(10).string(message.locale);
+    }
+    if (message.message !== "") {
+      writer.uint32(18).string(message.message);
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): Error_LocalizedMessage {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseError_LocalizedMessage();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.locale = reader.string();
+          break;
+        case 2:
+          message.message = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<Error_LocalizedMessage>
+  ): Error_LocalizedMessage {
+    const message = createBaseError_LocalizedMessage();
+    message.locale = object.locale ?? "";
+    message.message = object.message ?? "";
+    return message;
+  },
+};
+
+function createBaseError_MetadataEntry(): Error_MetadataEntry {
+  return { key: "", value: "" };
+}
+
+export const Error_MetadataEntry = {
+  encode(
+    message: Error_MetadataEntry,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.key !== "") {
+      writer.uint32(10).string(message.key);
+    }
+    if (message.value !== "") {
+      writer.uint32(18).string(message.value);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Error_MetadataEntry {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseError_MetadataEntry();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.key = reader.string();
+          break;
+        case 2:
+          message.value = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Error_MetadataEntry>): Error_MetadataEntry {
+    const message = createBaseError_MetadataEntry();
+    message.key = object.key ?? "";
+    message.value = object.value ?? "";
+    return message;
+  },
+};
+
+function createBaseFilter(): Filter {
+  return { op: "", field: "", value: undefined };
+}
+
+export const Filter = {
+  encode(
+    message: Filter,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.op !== "") {
+      writer.uint32(10).string(message.op);
+    }
+    if (message.field !== "") {
+      writer.uint32(18).string(message.field);
+    }
+    if (message.value !== undefined) {
+      Value.encode(
+        Value.wrap(message.value),
+        writer.uint32(26).fork()
+      ).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Filter {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFilter();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.op = reader.string();
+          break;
+        case 2:
+          message.field = reader.string();
+          break;
+        case 3:
+          message.value = Value.unwrap(Value.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Filter>): Filter {
+    const message = createBaseFilter();
+    message.op = object.op ?? "";
+    message.field = object.field ?? "";
+    message.value = object.value ?? undefined;
+    return message;
+  },
+};
+
+function createBaseFindOptions(): FindOptions {
+  return {
+    sort: [],
+    pageNum: 0,
+    pageSize: 0,
+    fields: [],
+    excludeFields: false,
+  };
+}
+
+export const FindOptions = {
+  encode(
+    message: FindOptions,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.sort) {
+      writer.uint32(10).string(v!);
+    }
+    if (message.pageNum !== 0) {
+      writer.uint32(16).int32(message.pageNum);
+    }
+    if (message.pageSize !== 0) {
+      writer.uint32(24).int32(message.pageSize);
+    }
+    for (const v of message.fields) {
+      writer.uint32(34).string(v!);
+    }
+    if (message.excludeFields === true) {
+      writer.uint32(40).bool(message.excludeFields);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): FindOptions {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFindOptions();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.sort.push(reader.string());
+          break;
+        case 2:
+          message.pageNum = reader.int32();
+          break;
+        case 3:
+          message.pageSize = reader.int32();
+          break;
+        case 4:
+          message.fields.push(reader.string());
+          break;
+        case 5:
+          message.excludeFields = reader.bool();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<FindOptions>): FindOptions {
+    const message = createBaseFindOptions();
+    message.sort = object.sort?.map((e) => e) || [];
+    message.pageNum = object.pageNum ?? 0;
+    message.pageSize = object.pageSize ?? 0;
+    message.fields = object.fields?.map((e) => e) || [];
+    message.excludeFields = object.excludeFields ?? false;
+    return message;
+  },
+};
+
+function createBaseRule(): Rule {
+  return {
+    collectionId: "",
+    actions: [],
+    access: 0,
+    hiddenFields: [],
+    readonlyFields: [],
+    writeonlyFields: [],
+    readFilter: "",
+    writeFilter: "",
+  };
+}
+
+export const Rule = {
+  encode(message: Rule, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
+    if (message.collectionId !== "") {
+      writer.uint32(10).string(message.collectionId);
+    }
+    writer.uint32(18).fork();
+    for (const v of message.actions) {
+      writer.int32(v);
+    }
+    writer.ldelim();
+    if (message.access !== 0) {
+      writer.uint32(24).int32(message.access);
+    }
+    for (const v of message.hiddenFields) {
+      writer.uint32(42).string(v!);
+    }
+    for (const v of message.readonlyFields) {
+      writer.uint32(50).string(v!);
+    }
+    for (const v of message.writeonlyFields) {
+      writer.uint32(58).string(v!);
+    }
+    if (message.readFilter !== "") {
+      writer.uint32(66).string(message.readFilter);
+    }
+    if (message.writeFilter !== "") {
+      writer.uint32(74).string(message.writeFilter);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Rule {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseRule();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.collectionId = reader.string();
+          break;
+        case 2:
+          if ((tag & 7) === 2) {
+            const end2 = reader.uint32() + reader.pos;
+            while (reader.pos < end2) {
+              message.actions.push(reader.int32() as any);
+            }
+          } else {
+            message.actions.push(reader.int32() as any);
+          }
+          break;
+        case 3:
+          message.access = reader.int32() as any;
+          break;
+        case 5:
+          message.hiddenFields.push(reader.string());
+          break;
+        case 6:
+          message.readonlyFields.push(reader.string());
+          break;
+        case 7:
+          message.writeonlyFields.push(reader.string());
+          break;
+        case 8:
+          message.readFilter = reader.string();
+          break;
+        case 9:
+          message.writeFilter = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Rule>): Rule {
+    const message = createBaseRule();
+    message.collectionId = object.collectionId ?? "";
+    message.actions = object.actions?.map((e) => e) || [];
+    message.access = object.access ?? 0;
+    message.hiddenFields = object.hiddenFields?.map((e) => e) || [];
+    message.readonlyFields = object.readonlyFields?.map((e) => e) || [];
+    message.writeonlyFields = object.writeonlyFields?.map((e) => e) || [];
+    message.readFilter = object.readFilter ?? "";
+    message.writeFilter = object.writeFilter ?? "";
+    return message;
+  },
+};
+
+function createBaseCollaborator(): Collaborator {
+  return { spaceId: "", subject: "", role: "" };
+}
+
+export const Collaborator = {
+  encode(
+    message: Collaborator,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.subject !== "") {
+      writer.uint32(18).string(message.subject);
+    }
+    if (message.role !== "") {
+      writer.uint32(26).string(message.role);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Collaborator {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCollaborator();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.subject = reader.string();
+          break;
+        case 3:
+          message.role = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Collaborator>): Collaborator {
+    const message = createBaseCollaborator();
+    message.spaceId = object.spaceId ?? "";
+    message.subject = object.subject ?? "";
+    message.role = object.role ?? "";
+    return message;
+  },
+};
+
+function createBaseVersion(): Version {
+  return {
+    serverVersion: "",
+    apiVersion: "",
+    buildTime: "",
+    commit: "",
+    buildNumber: 0,
+  };
+}
+
+export const Version = {
+  encode(
+    message: Version,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.serverVersion !== "") {
+      writer.uint32(10).string(message.serverVersion);
+    }
+    if (message.apiVersion !== "") {
+      writer.uint32(18).string(message.apiVersion);
+    }
+    if (message.buildTime !== "") {
+      writer.uint32(26).string(message.buildTime);
+    }
+    if (message.commit !== "") {
+      writer.uint32(34).string(message.commit);
+    }
+    if (message.buildNumber !== 0) {
+      writer.uint32(40).int32(message.buildNumber);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Version {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseVersion();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.serverVersion = reader.string();
+          break;
+        case 2:
+          message.apiVersion = reader.string();
+          break;
+        case 3:
+          message.buildTime = reader.string();
+          break;
+        case 4:
+          message.commit = reader.string();
+          break;
+        case 5:
+          message.buildNumber = reader.int32();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Version>): Version {
+    const message = createBaseVersion();
+    message.serverVersion = object.serverVersion ?? "";
+    message.apiVersion = object.apiVersion ?? "";
+    message.buildTime = object.buildTime ?? "";
+    message.commit = object.commit ?? "";
+    message.buildNumber = object.buildNumber ?? 0;
+    return message;
+  },
+};
+
+declare var self: any | undefined;
+declare var window: any | undefined;
+declare var global: any | undefined;
+var globalThis: any = (() => {
+  if (typeof globalThis !== "undefined") return globalThis;
+  if (typeof self !== "undefined") return self;
+  if (typeof window !== "undefined") return window;
+  if (typeof global !== "undefined") return global;
+  throw "Unable to locate global object";
+})();
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
+
+function longToNumber(long: Long): number {
+  if (long.gt(Number.MAX_SAFE_INTEGER)) {
+    throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER");
+  }
+  return long.toNumber();
+}
+
+if (_m0.util.Long !== Long) {
+  _m0.util.Long = Long as any;
+  _m0.configure();
+}
diff --git a/clients/common/index.d.ts b/clients/common/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ccfb0e9c78dff61d22bfc685e8cf23d5c0926fcd
--- /dev/null
+++ b/clients/common/index.d.ts
@@ -0,0 +1,2 @@
+export * from './common';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/common/index.d.ts.map b/clients/common/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..d68da9bfd6c9e0e766776d648d711c343fde236c
--- /dev/null
+++ b/clients/common/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA"}
\ No newline at end of file
diff --git a/clients/common/index.js b/clients/common/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..259ef006d210f289efdf20ecdf1e6b139fad83d9
--- /dev/null
+++ b/clients/common/index.js
@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./common"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/common/index.js.map b/clients/common/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..9a82574a46940f84df0cf1940e8c3b0bab8d91ef
--- /dev/null
+++ b/clients/common/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAwB"}
\ No newline at end of file
diff --git a/clients/delivery/delivery.ts b/clients/delivery/delivery.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5bb279bd77e53016c813f1d2014eb8a7fad4dd6f
--- /dev/null
+++ b/clients/delivery/delivery.ts
@@ -0,0 +1,892 @@
+/* eslint-disable */
+import { Environment } from "../environments/environments";
+import { Collection } from "../collections/collections";
+import {
+  GetPublishedOptions,
+  Item,
+  Filter,
+  FindPublishedOptions,
+} from "../items/items";
+import { Locale } from "../locales/locales";
+import * as _m0 from "protobufjs/minimal";
+
+export interface ListLocalesRequest {
+  spaceId: string;
+}
+
+export interface ListLocalesResponse {
+  locales: Locale[];
+}
+
+export interface GetEnvironmentRequest {
+  spaceId: string;
+  envId: string;
+}
+
+export interface GetEnvironmentResponse {
+  env?: Environment;
+}
+
+export interface ListEnvironmentsRequest {
+  spaceId: string;
+}
+
+export interface ListEnvironmentsResponse {
+  envs: Environment[];
+}
+
+export interface GetCollectionRequest {
+  spaceId: string;
+  envId: string;
+  collectionId: string;
+}
+
+export interface GetCollectionResponse {
+  collection?: Collection;
+}
+
+export interface ListCollectionsRequest {
+  spaceId: string;
+  envId: string;
+}
+
+export interface ListCollectionsResponse {
+  collections: Collection[];
+}
+
+export interface GetItemRequest {
+  spaceId: string;
+  envId: string;
+  collectionId: string;
+  itemId: string;
+  options?: GetPublishedOptions;
+}
+
+export interface GetItemResponse {
+  item?: Item;
+}
+
+export interface FindItemsRequest {
+  spaceId: string;
+  envId: string;
+  collectionId: string;
+  filter?: Filter;
+  options?: FindPublishedOptions;
+}
+
+export interface FindItemsResponse {
+  items: Item[];
+  total: number;
+}
+
+function createBaseListLocalesRequest(): ListLocalesRequest {
+  return { spaceId: "" };
+}
+
+export const ListLocalesRequest = {
+  encode(
+    message: ListLocalesRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ListLocalesRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListLocalesRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListLocalesRequest>): ListLocalesRequest {
+    const message = createBaseListLocalesRequest();
+    message.spaceId = object.spaceId ?? "";
+    return message;
+  },
+};
+
+function createBaseListLocalesResponse(): ListLocalesResponse {
+  return { locales: [] };
+}
+
+export const ListLocalesResponse = {
+  encode(
+    message: ListLocalesResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.locales) {
+      Locale.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ListLocalesResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListLocalesResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.locales.push(Locale.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListLocalesResponse>): ListLocalesResponse {
+    const message = createBaseListLocalesResponse();
+    message.locales = object.locales?.map((e) => Locale.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseGetEnvironmentRequest(): GetEnvironmentRequest {
+  return { spaceId: "", envId: "" };
+}
+
+export const GetEnvironmentRequest = {
+  encode(
+    message: GetEnvironmentRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): GetEnvironmentRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetEnvironmentRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<GetEnvironmentRequest>
+  ): GetEnvironmentRequest {
+    const message = createBaseGetEnvironmentRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    return message;
+  },
+};
+
+function createBaseGetEnvironmentResponse(): GetEnvironmentResponse {
+  return { env: undefined };
+}
+
+export const GetEnvironmentResponse = {
+  encode(
+    message: GetEnvironmentResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.env !== undefined) {
+      Environment.encode(message.env, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): GetEnvironmentResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetEnvironmentResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.env = Environment.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<GetEnvironmentResponse>
+  ): GetEnvironmentResponse {
+    const message = createBaseGetEnvironmentResponse();
+    message.env =
+      object.env !== undefined && object.env !== null
+        ? Environment.fromPartial(object.env)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseListEnvironmentsRequest(): ListEnvironmentsRequest {
+  return { spaceId: "" };
+}
+
+export const ListEnvironmentsRequest = {
+  encode(
+    message: ListEnvironmentsRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): ListEnvironmentsRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListEnvironmentsRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<ListEnvironmentsRequest>
+  ): ListEnvironmentsRequest {
+    const message = createBaseListEnvironmentsRequest();
+    message.spaceId = object.spaceId ?? "";
+    return message;
+  },
+};
+
+function createBaseListEnvironmentsResponse(): ListEnvironmentsResponse {
+  return { envs: [] };
+}
+
+export const ListEnvironmentsResponse = {
+  encode(
+    message: ListEnvironmentsResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.envs) {
+      Environment.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): ListEnvironmentsResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListEnvironmentsResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.envs.push(Environment.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<ListEnvironmentsResponse>
+  ): ListEnvironmentsResponse {
+    const message = createBaseListEnvironmentsResponse();
+    message.envs = object.envs?.map((e) => Environment.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseGetCollectionRequest(): GetCollectionRequest {
+  return { spaceId: "", envId: "", collectionId: "" };
+}
+
+export const GetCollectionRequest = {
+  encode(
+    message: GetCollectionRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    if (message.collectionId !== "") {
+      writer.uint32(26).string(message.collectionId);
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): GetCollectionRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetCollectionRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        case 3:
+          message.collectionId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetCollectionRequest>): GetCollectionRequest {
+    const message = createBaseGetCollectionRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.collectionId = object.collectionId ?? "";
+    return message;
+  },
+};
+
+function createBaseGetCollectionResponse(): GetCollectionResponse {
+  return { collection: undefined };
+}
+
+export const GetCollectionResponse = {
+  encode(
+    message: GetCollectionResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.collection !== undefined) {
+      Collection.encode(message.collection, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): GetCollectionResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetCollectionResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.collection = Collection.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<GetCollectionResponse>
+  ): GetCollectionResponse {
+    const message = createBaseGetCollectionResponse();
+    message.collection =
+      object.collection !== undefined && object.collection !== null
+        ? Collection.fromPartial(object.collection)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseListCollectionsRequest(): ListCollectionsRequest {
+  return { spaceId: "", envId: "" };
+}
+
+export const ListCollectionsRequest = {
+  encode(
+    message: ListCollectionsRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): ListCollectionsRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListCollectionsRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<ListCollectionsRequest>
+  ): ListCollectionsRequest {
+    const message = createBaseListCollectionsRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    return message;
+  },
+};
+
+function createBaseListCollectionsResponse(): ListCollectionsResponse {
+  return { collections: [] };
+}
+
+export const ListCollectionsResponse = {
+  encode(
+    message: ListCollectionsResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.collections) {
+      Collection.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): ListCollectionsResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListCollectionsResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.collections.push(Collection.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<ListCollectionsResponse>
+  ): ListCollectionsResponse {
+    const message = createBaseListCollectionsResponse();
+    message.collections =
+      object.collections?.map((e) => Collection.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseGetItemRequest(): GetItemRequest {
+  return {
+    spaceId: "",
+    envId: "",
+    collectionId: "",
+    itemId: "",
+    options: undefined,
+  };
+}
+
+export const GetItemRequest = {
+  encode(
+    message: GetItemRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    if (message.collectionId !== "") {
+      writer.uint32(26).string(message.collectionId);
+    }
+    if (message.itemId !== "") {
+      writer.uint32(42).string(message.itemId);
+    }
+    if (message.options !== undefined) {
+      GetPublishedOptions.encode(
+        message.options,
+        writer.uint32(50).fork()
+      ).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetItemRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetItemRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        case 3:
+          message.collectionId = reader.string();
+          break;
+        case 5:
+          message.itemId = reader.string();
+          break;
+        case 6:
+          message.options = GetPublishedOptions.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetItemRequest>): GetItemRequest {
+    const message = createBaseGetItemRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.collectionId = object.collectionId ?? "";
+    message.itemId = object.itemId ?? "";
+    message.options =
+      object.options !== undefined && object.options !== null
+        ? GetPublishedOptions.fromPartial(object.options)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseGetItemResponse(): GetItemResponse {
+  return { item: undefined };
+}
+
+export const GetItemResponse = {
+  encode(
+    message: GetItemResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.item !== undefined) {
+      Item.encode(message.item, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetItemResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetItemResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.item = Item.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetItemResponse>): GetItemResponse {
+    const message = createBaseGetItemResponse();
+    message.item =
+      object.item !== undefined && object.item !== null
+        ? Item.fromPartial(object.item)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseFindItemsRequest(): FindItemsRequest {
+  return {
+    spaceId: "",
+    envId: "",
+    collectionId: "",
+    filter: undefined,
+    options: undefined,
+  };
+}
+
+export const FindItemsRequest = {
+  encode(
+    message: FindItemsRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    if (message.collectionId !== "") {
+      writer.uint32(26).string(message.collectionId);
+    }
+    if (message.filter !== undefined) {
+      Filter.encode(message.filter, writer.uint32(42).fork()).ldelim();
+    }
+    if (message.options !== undefined) {
+      FindPublishedOptions.encode(
+        message.options,
+        writer.uint32(50).fork()
+      ).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): FindItemsRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFindItemsRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        case 3:
+          message.collectionId = reader.string();
+          break;
+        case 5:
+          message.filter = Filter.decode(reader, reader.uint32());
+          break;
+        case 6:
+          message.options = FindPublishedOptions.decode(
+            reader,
+            reader.uint32()
+          );
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<FindItemsRequest>): FindItemsRequest {
+    const message = createBaseFindItemsRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.collectionId = object.collectionId ?? "";
+    message.filter =
+      object.filter !== undefined && object.filter !== null
+        ? Filter.fromPartial(object.filter)
+        : undefined;
+    message.options =
+      object.options !== undefined && object.options !== null
+        ? FindPublishedOptions.fromPartial(object.options)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseFindItemsResponse(): FindItemsResponse {
+  return { items: [], total: 0 };
+}
+
+export const FindItemsResponse = {
+  encode(
+    message: FindItemsResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.items) {
+      Item.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    if (message.total !== 0) {
+      writer.uint32(16).int32(message.total);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): FindItemsResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFindItemsResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.items.push(Item.decode(reader, reader.uint32()));
+          break;
+        case 2:
+          message.total = reader.int32();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<FindItemsResponse>): FindItemsResponse {
+    const message = createBaseFindItemsResponse();
+    message.items = object.items?.map((e) => Item.fromPartial(e)) || [];
+    message.total = object.total ?? 0;
+    return message;
+  },
+};
+
+export type DeliveryDefinition = typeof DeliveryDefinition;
+export const DeliveryDefinition = {
+  name: "Delivery",
+  fullName: "delivery.Delivery",
+  methods: {
+    listLocales: {
+      name: "ListLocales",
+      requestType: ListLocalesRequest,
+      requestStream: false,
+      responseType: ListLocalesResponse,
+      responseStream: false,
+      options: {},
+    },
+    getEnvironment: {
+      name: "GetEnvironment",
+      requestType: GetEnvironmentRequest,
+      requestStream: false,
+      responseType: GetEnvironmentResponse,
+      responseStream: false,
+      options: {},
+    },
+    listEnvironments: {
+      name: "ListEnvironments",
+      requestType: ListEnvironmentsRequest,
+      requestStream: false,
+      responseType: ListEnvironmentsResponse,
+      responseStream: false,
+      options: {},
+    },
+    getCollection: {
+      name: "GetCollection",
+      requestType: GetCollectionRequest,
+      requestStream: false,
+      responseType: GetCollectionResponse,
+      responseStream: false,
+      options: {},
+    },
+    listCollections: {
+      name: "ListCollections",
+      requestType: ListCollectionsRequest,
+      requestStream: false,
+      responseType: ListCollectionsResponse,
+      responseStream: false,
+      options: {},
+    },
+    getItem: {
+      name: "GetItem",
+      requestType: GetItemRequest,
+      requestStream: false,
+      responseType: GetItemResponse,
+      responseStream: false,
+      options: {},
+    },
+    findItems: {
+      name: "FindItems",
+      requestType: FindItemsRequest,
+      requestStream: false,
+      responseType: FindItemsResponse,
+      responseStream: false,
+      options: {},
+    },
+  },
+} as const;
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
diff --git a/clients/delivery/index.d.ts b/clients/delivery/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d28ad2cf306ef2b58d8ec4037ee8938e11d46d69
--- /dev/null
+++ b/clients/delivery/index.d.ts
@@ -0,0 +1,2 @@
+export * from './delivery';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/delivery/index.d.ts.map b/clients/delivery/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..81d14ab63768aa15896ab5e29a575183d48308ac
--- /dev/null
+++ b/clients/delivery/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA"}
\ No newline at end of file
diff --git a/clients/delivery/index.js b/clients/delivery/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..3bc9b9957b8dadf4de15a6b8f44876ec42b6afbb
--- /dev/null
+++ b/clients/delivery/index.js
@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./delivery"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/delivery/index.js.map b/clients/delivery/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..5f0a1275bea7fe5d714e71a9f52bc00734a23e62
--- /dev/null
+++ b/clients/delivery/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6CAA0B"}
\ No newline at end of file
diff --git a/clients/environments/environments.ts b/clients/environments/environments.ts
new file mode 100644
index 0000000000000000000000000000000000000000..76d9ac2f6ef5c38cd50878a6f44578bd839fd819
--- /dev/null
+++ b/clients/environments/environments.ts
@@ -0,0 +1,750 @@
+/* eslint-disable */
+import { Empty } from "../google/protobuf/empty";
+import * as _m0 from "protobufjs/minimal";
+
+export interface Environment {
+  id: string;
+  spaceId: string;
+  description: string;
+  state: Environment_State;
+  stateInfo: string;
+  aliases: string[];
+  config?: Config;
+}
+
+export enum Environment_State {
+  UNKNOWN = 0,
+  NEW = 1,
+  PREPARING = 2,
+  READY = 3,
+  ERROR = 4,
+  UNRECOGNIZED = -1,
+}
+
+export interface Config {
+  sourceId: string;
+  features: string[];
+}
+
+export interface CreateRequest {
+  env?: Environment;
+}
+
+export interface CreateResponse {
+  created?: Environment;
+}
+
+export interface ListRequest {
+  spaceId: string;
+}
+
+export interface ListResponse {
+  envs: Environment[];
+}
+
+export interface GetRequest {
+  spaceId: string;
+  envId: string;
+}
+
+export interface GetResponse {
+  env?: Environment;
+}
+
+export interface UpdateRequest {
+  env?: Environment;
+}
+
+export interface SetAliasRequest {
+  spaceId: string;
+  envId: string;
+  alias: string;
+}
+
+export interface RemoveAliasRequest {
+  spaceId: string;
+  envId: string;
+  alias: string;
+}
+
+export interface DeleteRequest {
+  spaceId: string;
+  envId: string;
+}
+
+function createBaseEnvironment(): Environment {
+  return {
+    id: "",
+    spaceId: "",
+    description: "",
+    state: 0,
+    stateInfo: "",
+    aliases: [],
+    config: undefined,
+  };
+}
+
+export const Environment = {
+  encode(
+    message: Environment,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.id !== "") {
+      writer.uint32(10).string(message.id);
+    }
+    if (message.spaceId !== "") {
+      writer.uint32(18).string(message.spaceId);
+    }
+    if (message.description !== "") {
+      writer.uint32(26).string(message.description);
+    }
+    if (message.state !== 0) {
+      writer.uint32(32).int32(message.state);
+    }
+    if (message.stateInfo !== "") {
+      writer.uint32(42).string(message.stateInfo);
+    }
+    for (const v of message.aliases) {
+      writer.uint32(50).string(v!);
+    }
+    if (message.config !== undefined) {
+      Config.encode(message.config, writer.uint32(82).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Environment {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseEnvironment();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.id = reader.string();
+          break;
+        case 2:
+          message.spaceId = reader.string();
+          break;
+        case 3:
+          message.description = reader.string();
+          break;
+        case 4:
+          message.state = reader.int32() as any;
+          break;
+        case 5:
+          message.stateInfo = reader.string();
+          break;
+        case 6:
+          message.aliases.push(reader.string());
+          break;
+        case 10:
+          message.config = Config.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Environment>): Environment {
+    const message = createBaseEnvironment();
+    message.id = object.id ?? "";
+    message.spaceId = object.spaceId ?? "";
+    message.description = object.description ?? "";
+    message.state = object.state ?? 0;
+    message.stateInfo = object.stateInfo ?? "";
+    message.aliases = object.aliases?.map((e) => e) || [];
+    message.config =
+      object.config !== undefined && object.config !== null
+        ? Config.fromPartial(object.config)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseConfig(): Config {
+  return { sourceId: "", features: [] };
+}
+
+export const Config = {
+  encode(
+    message: Config,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.sourceId !== "") {
+      writer.uint32(10).string(message.sourceId);
+    }
+    for (const v of message.features) {
+      writer.uint32(18).string(v!);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Config {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseConfig();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.sourceId = reader.string();
+          break;
+        case 2:
+          message.features.push(reader.string());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Config>): Config {
+    const message = createBaseConfig();
+    message.sourceId = object.sourceId ?? "";
+    message.features = object.features?.map((e) => e) || [];
+    return message;
+  },
+};
+
+function createBaseCreateRequest(): CreateRequest {
+  return { env: undefined };
+}
+
+export const CreateRequest = {
+  encode(
+    message: CreateRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.env !== undefined) {
+      Environment.encode(message.env, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CreateRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCreateRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.env = Environment.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CreateRequest>): CreateRequest {
+    const message = createBaseCreateRequest();
+    message.env =
+      object.env !== undefined && object.env !== null
+        ? Environment.fromPartial(object.env)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseCreateResponse(): CreateResponse {
+  return { created: undefined };
+}
+
+export const CreateResponse = {
+  encode(
+    message: CreateResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.created !== undefined) {
+      Environment.encode(message.created, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CreateResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCreateResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.created = Environment.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CreateResponse>): CreateResponse {
+    const message = createBaseCreateResponse();
+    message.created =
+      object.created !== undefined && object.created !== null
+        ? Environment.fromPartial(object.created)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseListRequest(): ListRequest {
+  return { spaceId: "" };
+}
+
+export const ListRequest = {
+  encode(
+    message: ListRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ListRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListRequest>): ListRequest {
+    const message = createBaseListRequest();
+    message.spaceId = object.spaceId ?? "";
+    return message;
+  },
+};
+
+function createBaseListResponse(): ListResponse {
+  return { envs: [] };
+}
+
+export const ListResponse = {
+  encode(
+    message: ListResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.envs) {
+      Environment.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ListResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.envs.push(Environment.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListResponse>): ListResponse {
+    const message = createBaseListResponse();
+    message.envs = object.envs?.map((e) => Environment.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseGetRequest(): GetRequest {
+  return { spaceId: "", envId: "" };
+}
+
+export const GetRequest = {
+  encode(
+    message: GetRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetRequest>): GetRequest {
+    const message = createBaseGetRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    return message;
+  },
+};
+
+function createBaseGetResponse(): GetResponse {
+  return { env: undefined };
+}
+
+export const GetResponse = {
+  encode(
+    message: GetResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.env !== undefined) {
+      Environment.encode(message.env, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.env = Environment.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetResponse>): GetResponse {
+    const message = createBaseGetResponse();
+    message.env =
+      object.env !== undefined && object.env !== null
+        ? Environment.fromPartial(object.env)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseUpdateRequest(): UpdateRequest {
+  return { env: undefined };
+}
+
+export const UpdateRequest = {
+  encode(
+    message: UpdateRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.env !== undefined) {
+      Environment.encode(message.env, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UpdateRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUpdateRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.env = Environment.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UpdateRequest>): UpdateRequest {
+    const message = createBaseUpdateRequest();
+    message.env =
+      object.env !== undefined && object.env !== null
+        ? Environment.fromPartial(object.env)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseSetAliasRequest(): SetAliasRequest {
+  return { spaceId: "", envId: "", alias: "" };
+}
+
+export const SetAliasRequest = {
+  encode(
+    message: SetAliasRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    if (message.alias !== "") {
+      writer.uint32(26).string(message.alias);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): SetAliasRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseSetAliasRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        case 3:
+          message.alias = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<SetAliasRequest>): SetAliasRequest {
+    const message = createBaseSetAliasRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.alias = object.alias ?? "";
+    return message;
+  },
+};
+
+function createBaseRemoveAliasRequest(): RemoveAliasRequest {
+  return { spaceId: "", envId: "", alias: "" };
+}
+
+export const RemoveAliasRequest = {
+  encode(
+    message: RemoveAliasRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    if (message.alias !== "") {
+      writer.uint32(26).string(message.alias);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): RemoveAliasRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseRemoveAliasRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        case 3:
+          message.alias = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<RemoveAliasRequest>): RemoveAliasRequest {
+    const message = createBaseRemoveAliasRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.alias = object.alias ?? "";
+    return message;
+  },
+};
+
+function createBaseDeleteRequest(): DeleteRequest {
+  return { spaceId: "", envId: "" };
+}
+
+export const DeleteRequest = {
+  encode(
+    message: DeleteRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): DeleteRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseDeleteRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<DeleteRequest>): DeleteRequest {
+    const message = createBaseDeleteRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    return message;
+  },
+};
+
+export type EnvironmentsDefinition = typeof EnvironmentsDefinition;
+export const EnvironmentsDefinition = {
+  name: "Environments",
+  fullName: "content.environments.Environments",
+  methods: {
+    create: {
+      name: "Create",
+      requestType: CreateRequest,
+      requestStream: false,
+      responseType: CreateResponse,
+      responseStream: false,
+      options: {},
+    },
+    get: {
+      name: "Get",
+      requestType: GetRequest,
+      requestStream: false,
+      responseType: GetResponse,
+      responseStream: false,
+      options: {},
+    },
+    list: {
+      name: "List",
+      requestType: ListRequest,
+      requestStream: false,
+      responseType: ListResponse,
+      responseStream: false,
+      options: {},
+    },
+    update: {
+      name: "Update",
+      requestType: UpdateRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    setAlias: {
+      name: "SetAlias",
+      requestType: SetAliasRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    removeAlias: {
+      name: "RemoveAlias",
+      requestType: RemoveAliasRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    delete: {
+      name: "Delete",
+      requestType: DeleteRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+  },
+} as const;
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
diff --git a/clients/environments/index.d.ts b/clients/environments/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..efa15b47b8a5d50025ff6e20ab0b933b4b8e818f
--- /dev/null
+++ b/clients/environments/index.d.ts
@@ -0,0 +1,2 @@
+export * from './environments';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/environments/index.d.ts.map b/clients/environments/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..1b34c678d771d83f1d8c95210ee0b1b78810a8e6
--- /dev/null
+++ b/clients/environments/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA"}
\ No newline at end of file
diff --git a/clients/environments/index.js b/clients/environments/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..4c6b7e1c5cfab825857c7e3b9850b2ef1cf669a8
--- /dev/null
+++ b/clients/environments/index.js
@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./environments"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/environments/index.js.map b/clients/environments/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..29e3cd6eb524cb2336ac607b6ede7095b93d37dd
--- /dev/null
+++ b/clients/environments/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iDAA8B"}
\ No newline at end of file
diff --git a/clients/extensions/extension.ts b/clients/extensions/extension.ts
new file mode 100644
index 0000000000000000000000000000000000000000..04b0f1d9fd11ba5849e1d2169f25dd81ce538844
--- /dev/null
+++ b/clients/extensions/extension.ts
@@ -0,0 +1,1347 @@
+/* eslint-disable */
+import { Reference } from "../references/references";
+import * as _m0 from "protobufjs/minimal";
+
+/**
+ * # Расширения (Extensions)
+ *
+ * Расширения представляют собой отдельные сервисы предоставляющие дополнительные возможности для пользователей. Сервис
+ * может предоставлять несколько расширений одновременно.
+ *
+ * Для координации взаимодействия используется сервис менеджер расширений (Extension Manager). Для предоставления своих функций в систему сервис должен
+ * зарегистрироваться на контроллере.
+ */
+
+export interface InstallRequest {
+  /** Список расширений для установки */
+  extensions: string[];
+  /** Пространство для установки расширений */
+  spaceId: string;
+  /** Идентификатор окружения для установки (по умолчанию master) */
+  envId: string;
+  /** Игнорировать и автоматически исправлять ошибки установки */
+  force: boolean;
+}
+
+export interface ExtensionRequestResult {
+  /** Состояние расширение */
+  state: ExtensionRequestResult_State;
+  /** Имя расширения */
+  extension: string;
+  /** Сообщение */
+  msg: string;
+  /** Ошибка (state == ERROR) */
+  error: string;
+  /** Доступно обновление */
+  updateAvailable: boolean;
+}
+
+export enum ExtensionRequestResult_State {
+  /** OK - Запрос завершен */
+  OK = 0,
+  /** ERROR - Возникла ошибка */
+  ERROR = 1,
+  /** PENDING - Запрос ожидает выполнения */
+  PENDING = 2,
+  /** IN_PROGRESS - Запрос выполняется */
+  IN_PROGRESS = 3,
+  UNRECOGNIZED = -1,
+}
+
+export interface InstallResponse {
+  /** Список состояний расширений после установки */
+  results: ExtensionRequestResult[];
+}
+
+export interface UninstallRequest {
+  /** Список расширений для удаления */
+  extensions: string[];
+  /** Пространство для удаления расширений */
+  spaceId: string;
+  /** Идентификатор окружения для установки (по умолчанию master) */
+  envId: string;
+  /** Удалить все коллекции и данные */
+  remove: boolean;
+  /** Удалять расширения вне зависимости от возможных ошибок, без учета зависимостей */
+  force: boolean;
+}
+
+export interface UninstallResponse {
+  /** Список состояний расширений после удаления */
+  results: ExtensionRequestResult[];
+}
+
+export interface UpdateRequest {
+  /** Список расширений для удаления */
+  extensions: string[];
+  /** Пространство для удаления расширений */
+  spaceId: string;
+  /** Идентификатор окружения для установки (по умолчанию master) */
+  envId: string;
+  /** Выполнять обновление и автоматически исправлять ошибки */
+  force: boolean;
+}
+
+export interface UpdateResponse {
+  /** Список состояний расширений после удаления */
+  results: ExtensionRequestResult[];
+}
+
+export interface CheckRequest {
+  /** Список расширений для удаления */
+  extensions: string[];
+  /** Пространство для удаления расширений */
+  spaceId: string;
+  /** Идентификатор окружения для установки (по умолчанию master) */
+  envId: string;
+}
+
+export interface CheckResponse {
+  /** Список состояний расширений */
+  results: ExtensionRequestResult[];
+}
+
+/** ActionRequest - запрос на выполнение действия к расширению (или менеджеру расширений) */
+export interface ActionRequest {
+  extension: string;
+  action: string;
+  spaceId: string;
+  envId: string;
+  collectionId: string;
+  itemId: string;
+  itemIds: string[];
+  /**
+   * Поля к которым применимо действие. В случае если действие выполняется из списка записей, содержит перечень
+   * полей которые пользователь выбрал для отображения в интерфейсе.
+   */
+  fields: string[];
+  metadata: { [key: string]: string };
+  /** Ссылки на записи используемые для выполнения действия (назначение ссылок зависит от действия и расширения) */
+  refs: Reference[];
+  /**
+   * Ссылка на документ с параметрами выполнения Action.
+   * Чтобы при выполнении действия открывалась форма параметров, необходимо указать `Action.params_collection`
+   */
+  params?: Reference;
+}
+
+export interface ActionRequest_MetadataEntry {
+  key: string;
+  value: string;
+}
+
+export interface ActionResponse {
+  /** Состояние расширение */
+  state: ActionResponse_State;
+  /** Сообщение о выполнении действия */
+  msg: string;
+  /** Сообщение в случае ошибки */
+  error: string;
+  /** Следующие возможные действия. Интерфейс отображает как варианты дальнейших действий пользователя */
+  next: Action[];
+  /** Метаданные запроса */
+  metadata: { [key: string]: string };
+  /** Ссылки на записи (назначение ссылок зависит от действия и расширения) */
+  refs: Reference[];
+}
+
+export enum ActionResponse_State {
+  /** DONE - Запрос завершен */
+  DONE = 0,
+  /** ERROR - Возникла ошибка */
+  ERROR = 1,
+  /** PENDING - Запрос ожидает выполнения */
+  PENDING = 2,
+  /** IN_PROGRESS - Запрос выполняется */
+  IN_PROGRESS = 3,
+  UNRECOGNIZED = -1,
+}
+
+export interface ActionResponse_MetadataEntry {
+  key: string;
+  value: string;
+}
+
+/**
+ * Action описывает как коллекцию в системе с предуставновленными действиями, так и возможные дальнейшие действия после
+ * получения ответа  (см. `ActionResponse.next`)
+ *
+ * Если поле `request` присутствует, но не все требуемые поля заполнены, то значения для них берутся из текущих значений.
+ *
+ * Коллекция: space_actions (Пространство/Действия)
+ * Действия сохраненные в коллекции не содержат поля `request`. Значение заполняется текущими значениями.
+ *
+ * Пользовательские действия добавляются при установке расширений или при
+ * настройке в системную коллекции `Пространство/Действия` (system_actions). Расширения самостоятельно контролирует создание необходимых
+ * им действий в коллекции.
+ *
+ * Интерфейс загружает пользовательские действия и отображает их в интерфейсе соответствующим образом.
+ */
+export interface Action {
+  /** Расширение */
+  extension: string;
+  /** Идентификатор действия */
+  action: string;
+  /** Название действия для отображения в интерфейсе (пункт меню, кнопка). */
+  name: string;
+  /** Описание действия для отображения в интерфейсе */
+  description: string;
+  /** Название иконки для отображения действия в интерфейсе */
+  icon: string;
+  /** Изображение для отображения в действия в интерфейсе */
+  image?: Reference;
+  /** Группы отображения действия в интерфейсе */
+  groups: string[];
+  /** Указывает на что направлено действие */
+  kind: Action_Kind;
+  /** Классы данных к которым применимо действие (название коллекций или специальных групп в рамках которых данное действие применимо) */
+  classes: string[];
+  /**
+   * Для `CREATE` действуют следующие правила:
+   * - Для создание записей в коллекции применимы действия которые содержат в classes название коллекции
+   * - Для создания записей в виджетах которые допускают создание записей (Block/BlockList) применимы действия которые содержат:
+   *   - в classes хотя бы одно значение из classes виджета
+   *   - если у виджета не указан classes, тогда названия коллекций которые могут быть использованы для создания элементов в поле (allowed_collections)
+   */
+  refs: Reference[];
+  /**
+   * Коллекция для сохранения параметрами действия. Если параметр указан, то при выполнении действия будет открываться
+   * форма создания записи в указанной коллекции
+   */
+  paramsCollection: string;
+  /** Параметры запроса (используется в случае `ActionResponse.next`) */
+  request?: ActionRequest;
+  /** Флаг указывающий что действие переносить пользователя в другую часть интерфейса, а не отправляет запрос на сервер */
+  navigationAction: boolean;
+  /**
+   * navigation_route - Строка шаблон для перехода в интерфейсе
+   * При указании полного адреса (http(s)://xyz), URL открывается в новом окне браузера
+   * Относительный адрес в пользовательском интерфейсе переносит пользователя в соответствующий раздел без перезагрузки приложения
+   *
+   * Переменные `:var` заменяются на текуще значение в пользовательском интерфейсе (Пример: `/spaces/:spaceId/envs/:envId/cols/:colId`)
+   * Перечень переменных для подстановки:
+   * - :spaceId
+   * - :envId
+   * - :colId
+   * - :itemId
+   */
+  navigationRoute: string;
+}
+
+/**
+ * Kind описывает c какой сущность системы связано действие и что требуется передать в качестве параметров
+ * Интерфейс загружает пользовательские действия и отображает их в интерфейсе в зависимости от ActionType.
+ */
+export enum Action_Kind {
+  /** DEFAULT - Действие не отображается в интерфейсе и могут используется для выполнения дополнительных запросов (см. `ActionResponse.next`) или напрямую из сторонних приложений. */
+  DEFAULT = 0,
+  /** SPACE - Действие связано с пространством (требуется передача space_id). Отображается в меню "Действия". */
+  SPACE = 1,
+  /** ENVIRONMENT - Действие связано с окружением (требуется передача space_id, env_id). Отображается в меню "Действия". */
+  ENVIRONMENT = 2,
+  /** COLLECTION - Действие связано с коллекцией (требуется передача space_id, env_id, collection_id). Отображается на экране списка записей. */
+  COLLECTION = 3,
+  /** ITEM - Действие связано с записью (требуется передача space_id, env_id, collection_id, item_id). Отображается на экране редактирования записи. */
+  ITEM = 4,
+  /** ITEMS - Действие связано с несколькими записями (требуется передача space_id, env_id, collection_id, item_ids). Отображается на экране списка записей. */
+  ITEMS = 5,
+  /** REVISION - Действие связано с ревизией записи (требуется передача space_id, env_id, collection_id, item_id, rev_id). На данный момент не используется. */
+  REVISION = 6,
+  /** CREATE - Действие создание записи (требуется передача space_id, env_id, collection_id). */
+  CREATE = 7,
+  UNRECOGNIZED = -1,
+}
+
+function createBaseInstallRequest(): InstallRequest {
+  return { extensions: [], spaceId: "", envId: "", force: false };
+}
+
+export const InstallRequest = {
+  encode(
+    message: InstallRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.extensions) {
+      writer.uint32(80002).string(v!);
+    }
+    if (message.spaceId !== "") {
+      writer.uint32(80082).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(80162).string(message.envId);
+    }
+    if (message.force === true) {
+      writer.uint32(80800).bool(message.force);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): InstallRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseInstallRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 10000:
+          message.extensions.push(reader.string());
+          break;
+        case 10010:
+          message.spaceId = reader.string();
+          break;
+        case 10020:
+          message.envId = reader.string();
+          break;
+        case 10100:
+          message.force = reader.bool();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<InstallRequest>): InstallRequest {
+    const message = createBaseInstallRequest();
+    message.extensions = object.extensions?.map((e) => e) || [];
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.force = object.force ?? false;
+    return message;
+  },
+};
+
+function createBaseExtensionRequestResult(): ExtensionRequestResult {
+  return {
+    state: 0,
+    extension: "",
+    msg: "",
+    error: "",
+    updateAvailable: false,
+  };
+}
+
+export const ExtensionRequestResult = {
+  encode(
+    message: ExtensionRequestResult,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.state !== 0) {
+      writer.uint32(80000).int32(message.state);
+    }
+    if (message.extension !== "") {
+      writer.uint32(80802).string(message.extension);
+    }
+    if (message.msg !== "") {
+      writer.uint32(81602).string(message.msg);
+    }
+    if (message.error !== "") {
+      writer.uint32(82402).string(message.error);
+    }
+    if (message.updateAvailable === true) {
+      writer.uint32(83200).bool(message.updateAvailable);
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): ExtensionRequestResult {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseExtensionRequestResult();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 10000:
+          message.state = reader.int32() as any;
+          break;
+        case 10100:
+          message.extension = reader.string();
+          break;
+        case 10200:
+          message.msg = reader.string();
+          break;
+        case 10300:
+          message.error = reader.string();
+          break;
+        case 10400:
+          message.updateAvailable = reader.bool();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<ExtensionRequestResult>
+  ): ExtensionRequestResult {
+    const message = createBaseExtensionRequestResult();
+    message.state = object.state ?? 0;
+    message.extension = object.extension ?? "";
+    message.msg = object.msg ?? "";
+    message.error = object.error ?? "";
+    message.updateAvailable = object.updateAvailable ?? false;
+    return message;
+  },
+};
+
+function createBaseInstallResponse(): InstallResponse {
+  return { results: [] };
+}
+
+export const InstallResponse = {
+  encode(
+    message: InstallResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.results) {
+      ExtensionRequestResult.encode(v!, writer.uint32(80002).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): InstallResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseInstallResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 10000:
+          message.results.push(
+            ExtensionRequestResult.decode(reader, reader.uint32())
+          );
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<InstallResponse>): InstallResponse {
+    const message = createBaseInstallResponse();
+    message.results =
+      object.results?.map((e) => ExtensionRequestResult.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseUninstallRequest(): UninstallRequest {
+  return {
+    extensions: [],
+    spaceId: "",
+    envId: "",
+    remove: false,
+    force: false,
+  };
+}
+
+export const UninstallRequest = {
+  encode(
+    message: UninstallRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.extensions) {
+      writer.uint32(80002).string(v!);
+    }
+    if (message.spaceId !== "") {
+      writer.uint32(80082).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(80162).string(message.envId);
+    }
+    if (message.remove === true) {
+      writer.uint32(80800).bool(message.remove);
+    }
+    if (message.force === true) {
+      writer.uint32(81600).bool(message.force);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UninstallRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUninstallRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 10000:
+          message.extensions.push(reader.string());
+          break;
+        case 10010:
+          message.spaceId = reader.string();
+          break;
+        case 10020:
+          message.envId = reader.string();
+          break;
+        case 10100:
+          message.remove = reader.bool();
+          break;
+        case 10200:
+          message.force = reader.bool();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UninstallRequest>): UninstallRequest {
+    const message = createBaseUninstallRequest();
+    message.extensions = object.extensions?.map((e) => e) || [];
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.remove = object.remove ?? false;
+    message.force = object.force ?? false;
+    return message;
+  },
+};
+
+function createBaseUninstallResponse(): UninstallResponse {
+  return { results: [] };
+}
+
+export const UninstallResponse = {
+  encode(
+    message: UninstallResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.results) {
+      ExtensionRequestResult.encode(v!, writer.uint32(80002).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UninstallResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUninstallResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 10000:
+          message.results.push(
+            ExtensionRequestResult.decode(reader, reader.uint32())
+          );
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UninstallResponse>): UninstallResponse {
+    const message = createBaseUninstallResponse();
+    message.results =
+      object.results?.map((e) => ExtensionRequestResult.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseUpdateRequest(): UpdateRequest {
+  return { extensions: [], spaceId: "", envId: "", force: false };
+}
+
+export const UpdateRequest = {
+  encode(
+    message: UpdateRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.extensions) {
+      writer.uint32(80002).string(v!);
+    }
+    if (message.spaceId !== "") {
+      writer.uint32(80082).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(80162).string(message.envId);
+    }
+    if (message.force === true) {
+      writer.uint32(80800).bool(message.force);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UpdateRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUpdateRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 10000:
+          message.extensions.push(reader.string());
+          break;
+        case 10010:
+          message.spaceId = reader.string();
+          break;
+        case 10020:
+          message.envId = reader.string();
+          break;
+        case 10100:
+          message.force = reader.bool();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UpdateRequest>): UpdateRequest {
+    const message = createBaseUpdateRequest();
+    message.extensions = object.extensions?.map((e) => e) || [];
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.force = object.force ?? false;
+    return message;
+  },
+};
+
+function createBaseUpdateResponse(): UpdateResponse {
+  return { results: [] };
+}
+
+export const UpdateResponse = {
+  encode(
+    message: UpdateResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.results) {
+      ExtensionRequestResult.encode(v!, writer.uint32(80002).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UpdateResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUpdateResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 10000:
+          message.results.push(
+            ExtensionRequestResult.decode(reader, reader.uint32())
+          );
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UpdateResponse>): UpdateResponse {
+    const message = createBaseUpdateResponse();
+    message.results =
+      object.results?.map((e) => ExtensionRequestResult.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseCheckRequest(): CheckRequest {
+  return { extensions: [], spaceId: "", envId: "" };
+}
+
+export const CheckRequest = {
+  encode(
+    message: CheckRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.extensions) {
+      writer.uint32(80002).string(v!);
+    }
+    if (message.spaceId !== "") {
+      writer.uint32(80082).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(80162).string(message.envId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CheckRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCheckRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 10000:
+          message.extensions.push(reader.string());
+          break;
+        case 10010:
+          message.spaceId = reader.string();
+          break;
+        case 10020:
+          message.envId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CheckRequest>): CheckRequest {
+    const message = createBaseCheckRequest();
+    message.extensions = object.extensions?.map((e) => e) || [];
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    return message;
+  },
+};
+
+function createBaseCheckResponse(): CheckResponse {
+  return { results: [] };
+}
+
+export const CheckResponse = {
+  encode(
+    message: CheckResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.results) {
+      ExtensionRequestResult.encode(v!, writer.uint32(80002).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CheckResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCheckResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 10000:
+          message.results.push(
+            ExtensionRequestResult.decode(reader, reader.uint32())
+          );
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CheckResponse>): CheckResponse {
+    const message = createBaseCheckResponse();
+    message.results =
+      object.results?.map((e) => ExtensionRequestResult.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseActionRequest(): ActionRequest {
+  return {
+    extension: "",
+    action: "",
+    spaceId: "",
+    envId: "",
+    collectionId: "",
+    itemId: "",
+    itemIds: [],
+    fields: [],
+    metadata: {},
+    refs: [],
+    params: undefined,
+  };
+}
+
+export const ActionRequest = {
+  encode(
+    message: ActionRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.extension !== "") {
+      writer.uint32(8002).string(message.extension);
+    }
+    if (message.action !== "") {
+      writer.uint32(80802).string(message.action);
+    }
+    if (message.spaceId !== "") {
+      writer.uint32(84002).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(84082).string(message.envId);
+    }
+    if (message.collectionId !== "") {
+      writer.uint32(84162).string(message.collectionId);
+    }
+    if (message.itemId !== "") {
+      writer.uint32(84242).string(message.itemId);
+    }
+    for (const v of message.itemIds) {
+      writer.uint32(84322).string(v!);
+    }
+    for (const v of message.fields) {
+      writer.uint32(84402).string(v!);
+    }
+    Object.entries(message.metadata).forEach(([key, value]) => {
+      ActionRequest_MetadataEntry.encode(
+        { key: key as any, value },
+        writer.uint32(88002).fork()
+      ).ldelim();
+    });
+    for (const v of message.refs) {
+      Reference.encode(v!, writer.uint32(88082).fork()).ldelim();
+    }
+    if (message.params !== undefined) {
+      Reference.encode(message.params, writer.uint32(88162).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ActionRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseActionRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1000:
+          message.extension = reader.string();
+          break;
+        case 10100:
+          message.action = reader.string();
+          break;
+        case 10500:
+          message.spaceId = reader.string();
+          break;
+        case 10510:
+          message.envId = reader.string();
+          break;
+        case 10520:
+          message.collectionId = reader.string();
+          break;
+        case 10530:
+          message.itemId = reader.string();
+          break;
+        case 10540:
+          message.itemIds.push(reader.string());
+          break;
+        case 10550:
+          message.fields.push(reader.string());
+          break;
+        case 11000:
+          const entry11000 = ActionRequest_MetadataEntry.decode(
+            reader,
+            reader.uint32()
+          );
+          if (entry11000.value !== undefined) {
+            message.metadata[entry11000.key] = entry11000.value;
+          }
+          break;
+        case 11010:
+          message.refs.push(Reference.decode(reader, reader.uint32()));
+          break;
+        case 11020:
+          message.params = Reference.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ActionRequest>): ActionRequest {
+    const message = createBaseActionRequest();
+    message.extension = object.extension ?? "";
+    message.action = object.action ?? "";
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.collectionId = object.collectionId ?? "";
+    message.itemId = object.itemId ?? "";
+    message.itemIds = object.itemIds?.map((e) => e) || [];
+    message.fields = object.fields?.map((e) => e) || [];
+    message.metadata = Object.entries(object.metadata ?? {}).reduce<{
+      [key: string]: string;
+    }>((acc, [key, value]) => {
+      if (value !== undefined) {
+        acc[key] = String(value);
+      }
+      return acc;
+    }, {});
+    message.refs = object.refs?.map((e) => Reference.fromPartial(e)) || [];
+    message.params =
+      object.params !== undefined && object.params !== null
+        ? Reference.fromPartial(object.params)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseActionRequest_MetadataEntry(): ActionRequest_MetadataEntry {
+  return { key: "", value: "" };
+}
+
+export const ActionRequest_MetadataEntry = {
+  encode(
+    message: ActionRequest_MetadataEntry,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.key !== "") {
+      writer.uint32(10).string(message.key);
+    }
+    if (message.value !== "") {
+      writer.uint32(18).string(message.value);
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): ActionRequest_MetadataEntry {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseActionRequest_MetadataEntry();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.key = reader.string();
+          break;
+        case 2:
+          message.value = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<ActionRequest_MetadataEntry>
+  ): ActionRequest_MetadataEntry {
+    const message = createBaseActionRequest_MetadataEntry();
+    message.key = object.key ?? "";
+    message.value = object.value ?? "";
+    return message;
+  },
+};
+
+function createBaseActionResponse(): ActionResponse {
+  return { state: 0, msg: "", error: "", next: [], metadata: {}, refs: [] };
+}
+
+export const ActionResponse = {
+  encode(
+    message: ActionResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.state !== 0) {
+      writer.uint32(80000).int32(message.state);
+    }
+    if (message.msg !== "") {
+      writer.uint32(80802).string(message.msg);
+    }
+    if (message.error !== "") {
+      writer.uint32(81602).string(message.error);
+    }
+    for (const v of message.next) {
+      Action.encode(v!, writer.uint32(82402).fork()).ldelim();
+    }
+    Object.entries(message.metadata).forEach(([key, value]) => {
+      ActionResponse_MetadataEntry.encode(
+        { key: key as any, value },
+        writer.uint32(83202).fork()
+      ).ldelim();
+    });
+    for (const v of message.refs) {
+      Reference.encode(v!, writer.uint32(82562).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ActionResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseActionResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 10000:
+          message.state = reader.int32() as any;
+          break;
+        case 10100:
+          message.msg = reader.string();
+          break;
+        case 10200:
+          message.error = reader.string();
+          break;
+        case 10300:
+          message.next.push(Action.decode(reader, reader.uint32()));
+          break;
+        case 10400:
+          const entry10400 = ActionResponse_MetadataEntry.decode(
+            reader,
+            reader.uint32()
+          );
+          if (entry10400.value !== undefined) {
+            message.metadata[entry10400.key] = entry10400.value;
+          }
+          break;
+        case 10320:
+          message.refs.push(Reference.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ActionResponse>): ActionResponse {
+    const message = createBaseActionResponse();
+    message.state = object.state ?? 0;
+    message.msg = object.msg ?? "";
+    message.error = object.error ?? "";
+    message.next = object.next?.map((e) => Action.fromPartial(e)) || [];
+    message.metadata = Object.entries(object.metadata ?? {}).reduce<{
+      [key: string]: string;
+    }>((acc, [key, value]) => {
+      if (value !== undefined) {
+        acc[key] = String(value);
+      }
+      return acc;
+    }, {});
+    message.refs = object.refs?.map((e) => Reference.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseActionResponse_MetadataEntry(): ActionResponse_MetadataEntry {
+  return { key: "", value: "" };
+}
+
+export const ActionResponse_MetadataEntry = {
+  encode(
+    message: ActionResponse_MetadataEntry,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.key !== "") {
+      writer.uint32(10).string(message.key);
+    }
+    if (message.value !== "") {
+      writer.uint32(18).string(message.value);
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): ActionResponse_MetadataEntry {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseActionResponse_MetadataEntry();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.key = reader.string();
+          break;
+        case 2:
+          message.value = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<ActionResponse_MetadataEntry>
+  ): ActionResponse_MetadataEntry {
+    const message = createBaseActionResponse_MetadataEntry();
+    message.key = object.key ?? "";
+    message.value = object.value ?? "";
+    return message;
+  },
+};
+
+function createBaseAction(): Action {
+  return {
+    extension: "",
+    action: "",
+    name: "",
+    description: "",
+    icon: "",
+    image: undefined,
+    groups: [],
+    kind: 0,
+    classes: [],
+    refs: [],
+    paramsCollection: "",
+    request: undefined,
+    navigationAction: false,
+    navigationRoute: "",
+  };
+}
+
+export const Action = {
+  encode(
+    message: Action,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.extension !== "") {
+      writer.uint32(80002).string(message.extension);
+    }
+    if (message.action !== "") {
+      writer.uint32(80802).string(message.action);
+    }
+    if (message.name !== "") {
+      writer.uint32(81602).string(message.name);
+    }
+    if (message.description !== "") {
+      writer.uint32(81682).string(message.description);
+    }
+    if (message.icon !== "") {
+      writer.uint32(81762).string(message.icon);
+    }
+    if (message.image !== undefined) {
+      Reference.encode(message.image, writer.uint32(81842).fork()).ldelim();
+    }
+    for (const v of message.groups) {
+      writer.uint32(81922).string(v!);
+    }
+    if (message.kind !== 0) {
+      writer.uint32(82400).int32(message.kind);
+    }
+    for (const v of message.classes) {
+      writer.uint32(82482).string(v!);
+    }
+    for (const v of message.refs) {
+      Reference.encode(v!, writer.uint32(82562).fork()).ldelim();
+    }
+    if (message.paramsCollection !== "") {
+      writer.uint32(82642).string(message.paramsCollection);
+    }
+    if (message.request !== undefined) {
+      ActionRequest.encode(
+        message.request,
+        writer.uint32(83202).fork()
+      ).ldelim();
+    }
+    if (message.navigationAction === true) {
+      writer.uint32(84000).bool(message.navigationAction);
+    }
+    if (message.navigationRoute !== "") {
+      writer.uint32(84082).string(message.navigationRoute);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Action {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseAction();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 10000:
+          message.extension = reader.string();
+          break;
+        case 10100:
+          message.action = reader.string();
+          break;
+        case 10200:
+          message.name = reader.string();
+          break;
+        case 10210:
+          message.description = reader.string();
+          break;
+        case 10220:
+          message.icon = reader.string();
+          break;
+        case 10230:
+          message.image = Reference.decode(reader, reader.uint32());
+          break;
+        case 10240:
+          message.groups.push(reader.string());
+          break;
+        case 10300:
+          message.kind = reader.int32() as any;
+          break;
+        case 10310:
+          message.classes.push(reader.string());
+          break;
+        case 10320:
+          message.refs.push(Reference.decode(reader, reader.uint32()));
+          break;
+        case 10330:
+          message.paramsCollection = reader.string();
+          break;
+        case 10400:
+          message.request = ActionRequest.decode(reader, reader.uint32());
+          break;
+        case 10500:
+          message.navigationAction = reader.bool();
+          break;
+        case 10510:
+          message.navigationRoute = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Action>): Action {
+    const message = createBaseAction();
+    message.extension = object.extension ?? "";
+    message.action = object.action ?? "";
+    message.name = object.name ?? "";
+    message.description = object.description ?? "";
+    message.icon = object.icon ?? "";
+    message.image =
+      object.image !== undefined && object.image !== null
+        ? Reference.fromPartial(object.image)
+        : undefined;
+    message.groups = object.groups?.map((e) => e) || [];
+    message.kind = object.kind ?? 0;
+    message.classes = object.classes?.map((e) => e) || [];
+    message.refs = object.refs?.map((e) => Reference.fromPartial(e)) || [];
+    message.paramsCollection = object.paramsCollection ?? "";
+    message.request =
+      object.request !== undefined && object.request !== null
+        ? ActionRequest.fromPartial(object.request)
+        : undefined;
+    message.navigationAction = object.navigationAction ?? false;
+    message.navigationRoute = object.navigationRoute ?? "";
+    return message;
+  },
+};
+
+/** Extension - API расширения */
+export type ExtensionDefinition = typeof ExtensionDefinition;
+export const ExtensionDefinition = {
+  name: "Extension",
+  fullName: "extensions.Extension",
+  methods: {
+    /**
+     * Для установки расширения выполняется запрос к сервису с указанием расширений которые должны быть установлены. Если
+     * расширение уже установлено процесс возвращает ошибку.
+     */
+    install: {
+      name: "Install",
+      requestType: InstallRequest,
+      requestStream: false,
+      responseType: InstallResponse,
+      responseStream: false,
+      options: {},
+    },
+    /**
+     * Можно запросить проверку статуса установки для расширения. При этом расширение проверяет наличие необходимых данных в
+     * пространстве или наличие новой версии расширения и сообщает об этом. Никаких действий с данными пространства не
+     * производится.
+     */
+    check: {
+      name: "Check",
+      requestType: CheckRequest,
+      requestStream: false,
+      responseType: CheckResponse,
+      responseStream: false,
+      options: {},
+    },
+    /**
+     * Сервис выполняет необходимые действия с данными и миграции для соответствия нужной версии расширения.
+     * Если расширение не установлено процесс обновления возвращает ошибку.
+     */
+    update: {
+      name: "Update",
+      requestType: UpdateRequest,
+      requestStream: false,
+      responseType: UpdateResponse,
+      responseStream: false,
+      options: {},
+    },
+    /** Удаление расширения из пространства. */
+    uninstall: {
+      name: "Uninstall",
+      requestType: UninstallRequest,
+      requestStream: false,
+      responseType: UninstallResponse,
+      responseStream: false,
+      options: {},
+    },
+    /**
+     * Пользовательские Действия (Actions)
+     *
+     * Пользовательские действия позволяют расширить функционал пользовательского интерфейса путем
+     * добавления в интерфейс элементов взаимодействуя с которыми пользователь может вызывать реакцию на
+     * сервере или переход в интерфейсе.
+     *
+     * Пользовательские действия добавляются при установке расширений в системную коллекции `System/Actions`.
+     * Коллекция создается автоматически менеджером расширений. При установке так же отображается меню `Действия`
+     * доступное для всех пользователей.
+     *
+     * Примеры пользовательских действий:
+     * - "Собрать сайт" - добавляется Perxis.Web для сборки сайта, доступна пользователю через меню,
+     *   параметры space_id, env_id. При вызове выполняется запрос на сервер ProcessAction.
+     * - "Посмотреть задачи" - добавляется Tasks для перехода на коллекцию задач. Отображается в меню,
+     *   параметры space_id, env_id.
+     *
+     * Приложения так же могут использовать действия для вызова обработки в других приложениях при
+     * необходимости.
+     */
+    action: {
+      name: "Action",
+      requestType: ActionRequest,
+      requestStream: false,
+      responseType: ActionResponse,
+      responseStream: false,
+      options: {},
+    },
+  },
+} as const;
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
diff --git a/clients/extensions/index.d.ts b/clients/extensions/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1e4df2c024e7115c8a14353fe750c36b316176c0
--- /dev/null
+++ b/clients/extensions/index.d.ts
@@ -0,0 +1,3 @@
+export * from './manager';
+export * from './extension';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/extensions/index.d.ts.map b/clients/extensions/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..e56ea784abac8897fc7a518962c057e0a61987d0
--- /dev/null
+++ b/clients/extensions/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA"}
\ No newline at end of file
diff --git a/clients/extensions/index.js b/clients/extensions/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..df7e357c8173f3007beb9e31c9d604a29969212a
--- /dev/null
+++ b/clients/extensions/index.js
@@ -0,0 +1,19 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./manager"), exports);
+__exportStar(require("./extension"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/extensions/index.js.map b/clients/extensions/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..0a4280e00e5d93b58ca944005b2342a9158522a7
--- /dev/null
+++ b/clients/extensions/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAAyB;AACzB,8CAA2B"}
\ No newline at end of file
diff --git a/clients/extensions/manager.ts b/clients/extensions/manager.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a0938d9a0aceff4a3bf89497dad0d411c2b895a2
--- /dev/null
+++ b/clients/extensions/manager.ts
@@ -0,0 +1,735 @@
+/* eslint-disable */
+import * as _m0 from "protobufjs/minimal";
+
+/**
+ * # Менеджер расширений
+ *
+ * Реализует функционал по координации расширений в системе и служит единой точкой доступа для работы с расширениями:
+ * - Регистрирует все расширения в едином реестре
+ * - Предоставляет доступ к реестру расширений на получение доступных расширений в системе
+ * - Контролирует процесс установки расширения, устанавливает все необходимые зависимости в правильном порядке
+ * - Контролирует создание системной коллекции `system_extensions` (System/Extensions) и создание/удалений в ней установленных расширений
+ * - Контролирует создание системной коллекции `system_actions` (System/Actions). Выполняет удаление всех действий связанных
+ * с расширением при его удалении.
+ * - Выполняет переадресацию запросов на действия для расширений
+ *
+ * Менеджер расширений для контроля установленных расширений использует системные коллекции. При обращении к сервису контента
+ * используются системный уровень прав для создания необходимых коллекций и получения данных:
+ * 1. `system_extensions` (System Extensions) - доступна только системным пользователям
+ * 2. `system_actions` (System Actions) - по умолчанию доступна только системным пользователям, настройки доступа на чтение
+ * выдаются пользователям вручную. В зависимости от пользователя в интерфейсе отображаются те или иные доступные действия.
+ *
+ * Проверка наличия коллекций и создание в случае их отсутствия выполняется в момент установки расширений. После установки
+ * расширения в коллекцию `system_extensions` добавляется запись об установленном расширении. Действия добавляются в
+ * коллекцию `system_actions` расширениями по собственному усмотрению при установке.
+ *
+ * Для обращения к расширениям используются права текущего пользователя запрашивающего операцию. Если пользователь не
+ * обладает необходимыми правами для выполнения действия то операция вернет ошибку.
+ */
+
+/** ServiceDescription описание сервиса */
+export interface ExtensionDescriptor {
+  /** Имя расширения */
+  extension: string;
+  /** Название расширения */
+  title: string;
+  /** Описание расширения */
+  description: string;
+  /** Версия расширения */
+  version: string;
+  /** Описание версии */
+  versionDescription: string;
+  /** Зависимости от других расширений */
+  deps: string[];
+  /** Адрес для внутри сети, коммуникация между сервисами */
+  url: string;
+  /** Метаданные сервиса, смотрите документацию по сервису */
+  metadata: { [key: string]: string };
+}
+
+export interface ExtensionDescriptor_MetadataEntry {
+  key: string;
+  value: string;
+}
+
+export interface RegisterExtensionsRequest {
+  extensions: ExtensionDescriptor[];
+}
+
+export interface RegisterExtensionsResponse {}
+
+export interface UnregisterExtensionsRequest {
+  extensions: ExtensionDescriptor[];
+}
+
+export interface UnregisterExtensionsResponse {}
+
+export interface ListExtensionsFilter {
+  /** Список имен сервисов для получения результатов. Список может содержать регулярные выражения. */
+  extension: string[];
+}
+
+export interface ListExtensionsRequest {
+  filter?: ListExtensionsFilter;
+}
+
+export interface ListExtensionsResponse {
+  extensions: ExtensionDescriptor[];
+}
+
+export interface SpaceExtensions {
+  extension: string;
+  title: string;
+  version: string;
+  deps: string[];
+  state: SpaceExtensions_State;
+  /** Сообщение к ошибке */
+  statusError: string;
+  /** Сообщение к статусу */
+  statusMsg: string;
+}
+
+export enum SpaceExtensions_State {
+  PENDING = 0,
+  INSTALLED = 1,
+  IN_PROGRESS = 2,
+  FAIL = 3,
+  UNRECOGNIZED = -1,
+}
+
+function createBaseExtensionDescriptor(): ExtensionDescriptor {
+  return {
+    extension: "",
+    title: "",
+    description: "",
+    version: "",
+    versionDescription: "",
+    deps: [],
+    url: "",
+    metadata: {},
+  };
+}
+
+export const ExtensionDescriptor = {
+  encode(
+    message: ExtensionDescriptor,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.extension !== "") {
+      writer.uint32(80002).string(message.extension);
+    }
+    if (message.title !== "") {
+      writer.uint32(80082).string(message.title);
+    }
+    if (message.description !== "") {
+      writer.uint32(80162).string(message.description);
+    }
+    if (message.version !== "") {
+      writer.uint32(80802).string(message.version);
+    }
+    if (message.versionDescription !== "") {
+      writer.uint32(80882).string(message.versionDescription);
+    }
+    for (const v of message.deps) {
+      writer.uint32(81602).string(v!);
+    }
+    if (message.url !== "") {
+      writer.uint32(42).string(message.url);
+    }
+    Object.entries(message.metadata).forEach(([key, value]) => {
+      ExtensionDescriptor_MetadataEntry.encode(
+        { key: key as any, value },
+        writer.uint32(50).fork()
+      ).ldelim();
+    });
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ExtensionDescriptor {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseExtensionDescriptor();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 10000:
+          message.extension = reader.string();
+          break;
+        case 10010:
+          message.title = reader.string();
+          break;
+        case 10020:
+          message.description = reader.string();
+          break;
+        case 10100:
+          message.version = reader.string();
+          break;
+        case 10110:
+          message.versionDescription = reader.string();
+          break;
+        case 10200:
+          message.deps.push(reader.string());
+          break;
+        case 5:
+          message.url = reader.string();
+          break;
+        case 6:
+          const entry6 = ExtensionDescriptor_MetadataEntry.decode(
+            reader,
+            reader.uint32()
+          );
+          if (entry6.value !== undefined) {
+            message.metadata[entry6.key] = entry6.value;
+          }
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ExtensionDescriptor>): ExtensionDescriptor {
+    const message = createBaseExtensionDescriptor();
+    message.extension = object.extension ?? "";
+    message.title = object.title ?? "";
+    message.description = object.description ?? "";
+    message.version = object.version ?? "";
+    message.versionDescription = object.versionDescription ?? "";
+    message.deps = object.deps?.map((e) => e) || [];
+    message.url = object.url ?? "";
+    message.metadata = Object.entries(object.metadata ?? {}).reduce<{
+      [key: string]: string;
+    }>((acc, [key, value]) => {
+      if (value !== undefined) {
+        acc[key] = String(value);
+      }
+      return acc;
+    }, {});
+    return message;
+  },
+};
+
+function createBaseExtensionDescriptor_MetadataEntry(): ExtensionDescriptor_MetadataEntry {
+  return { key: "", value: "" };
+}
+
+export const ExtensionDescriptor_MetadataEntry = {
+  encode(
+    message: ExtensionDescriptor_MetadataEntry,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.key !== "") {
+      writer.uint32(10).string(message.key);
+    }
+    if (message.value !== "") {
+      writer.uint32(18).string(message.value);
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): ExtensionDescriptor_MetadataEntry {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseExtensionDescriptor_MetadataEntry();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.key = reader.string();
+          break;
+        case 2:
+          message.value = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<ExtensionDescriptor_MetadataEntry>
+  ): ExtensionDescriptor_MetadataEntry {
+    const message = createBaseExtensionDescriptor_MetadataEntry();
+    message.key = object.key ?? "";
+    message.value = object.value ?? "";
+    return message;
+  },
+};
+
+function createBaseRegisterExtensionsRequest(): RegisterExtensionsRequest {
+  return { extensions: [] };
+}
+
+export const RegisterExtensionsRequest = {
+  encode(
+    message: RegisterExtensionsRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.extensions) {
+      ExtensionDescriptor.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): RegisterExtensionsRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseRegisterExtensionsRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.extensions.push(
+            ExtensionDescriptor.decode(reader, reader.uint32())
+          );
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<RegisterExtensionsRequest>
+  ): RegisterExtensionsRequest {
+    const message = createBaseRegisterExtensionsRequest();
+    message.extensions =
+      object.extensions?.map((e) => ExtensionDescriptor.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseRegisterExtensionsResponse(): RegisterExtensionsResponse {
+  return {};
+}
+
+export const RegisterExtensionsResponse = {
+  encode(
+    _: RegisterExtensionsResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): RegisterExtensionsResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseRegisterExtensionsResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    _: DeepPartial<RegisterExtensionsResponse>
+  ): RegisterExtensionsResponse {
+    const message = createBaseRegisterExtensionsResponse();
+    return message;
+  },
+};
+
+function createBaseUnregisterExtensionsRequest(): UnregisterExtensionsRequest {
+  return { extensions: [] };
+}
+
+export const UnregisterExtensionsRequest = {
+  encode(
+    message: UnregisterExtensionsRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.extensions) {
+      ExtensionDescriptor.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): UnregisterExtensionsRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUnregisterExtensionsRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.extensions.push(
+            ExtensionDescriptor.decode(reader, reader.uint32())
+          );
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<UnregisterExtensionsRequest>
+  ): UnregisterExtensionsRequest {
+    const message = createBaseUnregisterExtensionsRequest();
+    message.extensions =
+      object.extensions?.map((e) => ExtensionDescriptor.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseUnregisterExtensionsResponse(): UnregisterExtensionsResponse {
+  return {};
+}
+
+export const UnregisterExtensionsResponse = {
+  encode(
+    _: UnregisterExtensionsResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): UnregisterExtensionsResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUnregisterExtensionsResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    _: DeepPartial<UnregisterExtensionsResponse>
+  ): UnregisterExtensionsResponse {
+    const message = createBaseUnregisterExtensionsResponse();
+    return message;
+  },
+};
+
+function createBaseListExtensionsFilter(): ListExtensionsFilter {
+  return { extension: [] };
+}
+
+export const ListExtensionsFilter = {
+  encode(
+    message: ListExtensionsFilter,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.extension) {
+      writer.uint32(10).string(v!);
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): ListExtensionsFilter {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListExtensionsFilter();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.extension.push(reader.string());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListExtensionsFilter>): ListExtensionsFilter {
+    const message = createBaseListExtensionsFilter();
+    message.extension = object.extension?.map((e) => e) || [];
+    return message;
+  },
+};
+
+function createBaseListExtensionsRequest(): ListExtensionsRequest {
+  return { filter: undefined };
+}
+
+export const ListExtensionsRequest = {
+  encode(
+    message: ListExtensionsRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.filter !== undefined) {
+      ListExtensionsFilter.encode(
+        message.filter,
+        writer.uint32(10).fork()
+      ).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): ListExtensionsRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListExtensionsRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.filter = ListExtensionsFilter.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<ListExtensionsRequest>
+  ): ListExtensionsRequest {
+    const message = createBaseListExtensionsRequest();
+    message.filter =
+      object.filter !== undefined && object.filter !== null
+        ? ListExtensionsFilter.fromPartial(object.filter)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseListExtensionsResponse(): ListExtensionsResponse {
+  return { extensions: [] };
+}
+
+export const ListExtensionsResponse = {
+  encode(
+    message: ListExtensionsResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.extensions) {
+      ExtensionDescriptor.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): ListExtensionsResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListExtensionsResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.extensions.push(
+            ExtensionDescriptor.decode(reader, reader.uint32())
+          );
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<ListExtensionsResponse>
+  ): ListExtensionsResponse {
+    const message = createBaseListExtensionsResponse();
+    message.extensions =
+      object.extensions?.map((e) => ExtensionDescriptor.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseSpaceExtensions(): SpaceExtensions {
+  return {
+    extension: "",
+    title: "",
+    version: "",
+    deps: [],
+    state: 0,
+    statusError: "",
+    statusMsg: "",
+  };
+}
+
+export const SpaceExtensions = {
+  encode(
+    message: SpaceExtensions,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.extension !== "") {
+      writer.uint32(80002).string(message.extension);
+    }
+    if (message.title !== "") {
+      writer.uint32(80082).string(message.title);
+    }
+    if (message.version !== "") {
+      writer.uint32(80802).string(message.version);
+    }
+    for (const v of message.deps) {
+      writer.uint32(81602).string(v!);
+    }
+    if (message.state !== 0) {
+      writer.uint32(82400).int32(message.state);
+    }
+    if (message.statusError !== "") {
+      writer.uint32(83202).string(message.statusError);
+    }
+    if (message.statusMsg !== "") {
+      writer.uint32(84002).string(message.statusMsg);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): SpaceExtensions {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseSpaceExtensions();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 10000:
+          message.extension = reader.string();
+          break;
+        case 10010:
+          message.title = reader.string();
+          break;
+        case 10100:
+          message.version = reader.string();
+          break;
+        case 10200:
+          message.deps.push(reader.string());
+          break;
+        case 10300:
+          message.state = reader.int32() as any;
+          break;
+        case 10400:
+          message.statusError = reader.string();
+          break;
+        case 10500:
+          message.statusMsg = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<SpaceExtensions>): SpaceExtensions {
+    const message = createBaseSpaceExtensions();
+    message.extension = object.extension ?? "";
+    message.title = object.title ?? "";
+    message.version = object.version ?? "";
+    message.deps = object.deps?.map((e) => e) || [];
+    message.state = object.state ?? 0;
+    message.statusError = object.statusError ?? "";
+    message.statusMsg = object.statusMsg ?? "";
+    return message;
+  },
+};
+
+/** ExtensionManager - менеджер расширений. Должен реализовывать так же сервис Extension */
+export type ExtensionManagerDefinition = typeof ExtensionManagerDefinition;
+export const ExtensionManagerDefinition = {
+  name: "ExtensionManager",
+  fullName: "extensions.ExtensionManager",
+  methods: {
+    /**
+     * ##  Регистрация расширений
+     *
+     * Регистрация\Дерегистрация происходить через сервис менеджера расширений (Extension Manager). В процессе регистрации сервис сообщает
+     * о поддерживаемых сервисом действиях (Actions) и версии сервиса и зависимостях:
+     * 1. Действия (Actions) - перечень действия которые обрабатываются сервисом. Включает в себя как системные действия,
+     * так и пользовательские, которые могут быть использованы в интерфейсе;
+     * 2. Имя сервиса/расширения - название сервиса внутри системы;
+     * 3. Версия сервиса - сервис сообщает текущую версию сервиса. Контроллер сообщает пользователю о возможности обновления
+     * расширения при смене версии;
+     * 4. Описание версии - содержит информацию об изменениях в последних версиях расширения;
+     * 5. Зависимости - перечень расширений которые необходимы сервису для функционирования. При установке сервиса
+     * все расширения от которых он зависит, будут так же установлены.
+     */
+    registerExtensions: {
+      name: "RegisterExtensions",
+      requestType: RegisterExtensionsRequest,
+      requestStream: false,
+      responseType: RegisterExtensionsResponse,
+      responseStream: false,
+      options: {},
+    },
+    unregisterExtensions: {
+      name: "UnregisterExtensions",
+      requestType: UnregisterExtensionsRequest,
+      requestStream: false,
+      responseType: UnregisterExtensionsResponse,
+      responseStream: false,
+      options: {},
+    },
+    /** Получить список зарегистрированных сервисов */
+    listExtensions: {
+      name: "ListExtensions",
+      requestType: ListExtensionsRequest,
+      requestStream: false,
+      responseType: ListExtensionsResponse,
+      responseStream: false,
+      options: {},
+    },
+  },
+} as const;
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
diff --git a/clients/files/files.ts b/clients/files/files.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fe13f2cc399493734b1843fd653a7d1f7de0637e
--- /dev/null
+++ b/clients/files/files.ts
@@ -0,0 +1,1033 @@
+/* eslint-disable */
+import { Empty } from "../google/protobuf/empty";
+import * as _m0 from "protobufjs/minimal";
+
+export interface File {
+  /** Уникальный идентификатор файла в хранилище */
+  id: string;
+  /** Имя файла */
+  name: string;
+  /** Размер файла */
+  size: number;
+  /** Mime-type файла */
+  mimeType: string;
+  /** Адрес для загрузки файла */
+  url: string;
+}
+
+export interface MultipartUpload {
+  file?: File;
+  /** Идентификатор загрузки хранилища */
+  uploadId: string;
+  /** Размер блока для загрузки */
+  partSize: number;
+  /** Адреса для загрузки пол */
+  partUrls: string[];
+  /** Идентификаторы загруженных блоков (S3 ETAGs) */
+  parts: CompletedPart[];
+}
+
+export interface Upload {
+  file?: File;
+  /** URL для загрузки файлов */
+  uploadUrl: string;
+}
+
+export interface CompletedPart {
+  number: number;
+  id: string;
+}
+
+export interface StartUploadRequest {
+  upload?: MultipartUpload;
+}
+
+export interface StartUploadResponse {
+  upload?: MultipartUpload;
+}
+
+export interface CompleteUploadRequest {
+  upload?: MultipartUpload;
+}
+
+export interface CompleteUploadResponse {
+  upload?: MultipartUpload;
+}
+
+export interface AbortUploadRequest {
+  upload?: MultipartUpload;
+}
+
+export interface AbortUploadResponse {}
+
+export interface MoveUploadRequest {
+  upload?: MultipartUpload;
+}
+
+export interface MoveUploadResponse {
+  file?: File;
+}
+
+export interface UploadRequest {
+  file?: File;
+}
+
+export interface UploadResponse {
+  upload?: Upload;
+}
+
+export interface GetFileRequest {
+  id: string;
+}
+
+export interface GetFileResponse {
+  file?: File;
+}
+
+export interface DeleteFileRequest {
+  file?: File;
+}
+
+export interface DeleteFileResponse {}
+
+function createBaseFile(): File {
+  return { id: "", name: "", size: 0, mimeType: "", url: "" };
+}
+
+export const File = {
+  encode(message: File, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
+    if (message.id !== "") {
+      writer.uint32(10).string(message.id);
+    }
+    if (message.name !== "") {
+      writer.uint32(18).string(message.name);
+    }
+    if (message.size !== 0) {
+      writer.uint32(24).int32(message.size);
+    }
+    if (message.mimeType !== "") {
+      writer.uint32(34).string(message.mimeType);
+    }
+    if (message.url !== "") {
+      writer.uint32(42).string(message.url);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): File {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFile();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.id = reader.string();
+          break;
+        case 2:
+          message.name = reader.string();
+          break;
+        case 3:
+          message.size = reader.int32();
+          break;
+        case 4:
+          message.mimeType = reader.string();
+          break;
+        case 5:
+          message.url = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<File>): File {
+    const message = createBaseFile();
+    message.id = object.id ?? "";
+    message.name = object.name ?? "";
+    message.size = object.size ?? 0;
+    message.mimeType = object.mimeType ?? "";
+    message.url = object.url ?? "";
+    return message;
+  },
+};
+
+function createBaseMultipartUpload(): MultipartUpload {
+  return {
+    file: undefined,
+    uploadId: "",
+    partSize: 0,
+    partUrls: [],
+    parts: [],
+  };
+}
+
+export const MultipartUpload = {
+  encode(
+    message: MultipartUpload,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.file !== undefined) {
+      File.encode(message.file, writer.uint32(10).fork()).ldelim();
+    }
+    if (message.uploadId !== "") {
+      writer.uint32(18).string(message.uploadId);
+    }
+    if (message.partSize !== 0) {
+      writer.uint32(24).int32(message.partSize);
+    }
+    for (const v of message.partUrls) {
+      writer.uint32(34).string(v!);
+    }
+    for (const v of message.parts) {
+      CompletedPart.encode(v!, writer.uint32(42).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): MultipartUpload {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseMultipartUpload();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.file = File.decode(reader, reader.uint32());
+          break;
+        case 2:
+          message.uploadId = reader.string();
+          break;
+        case 3:
+          message.partSize = reader.int32();
+          break;
+        case 4:
+          message.partUrls.push(reader.string());
+          break;
+        case 5:
+          message.parts.push(CompletedPart.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<MultipartUpload>): MultipartUpload {
+    const message = createBaseMultipartUpload();
+    message.file =
+      object.file !== undefined && object.file !== null
+        ? File.fromPartial(object.file)
+        : undefined;
+    message.uploadId = object.uploadId ?? "";
+    message.partSize = object.partSize ?? 0;
+    message.partUrls = object.partUrls?.map((e) => e) || [];
+    message.parts =
+      object.parts?.map((e) => CompletedPart.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseUpload(): Upload {
+  return { file: undefined, uploadUrl: "" };
+}
+
+export const Upload = {
+  encode(
+    message: Upload,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.file !== undefined) {
+      File.encode(message.file, writer.uint32(10).fork()).ldelim();
+    }
+    if (message.uploadUrl !== "") {
+      writer.uint32(18).string(message.uploadUrl);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Upload {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUpload();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.file = File.decode(reader, reader.uint32());
+          break;
+        case 2:
+          message.uploadUrl = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Upload>): Upload {
+    const message = createBaseUpload();
+    message.file =
+      object.file !== undefined && object.file !== null
+        ? File.fromPartial(object.file)
+        : undefined;
+    message.uploadUrl = object.uploadUrl ?? "";
+    return message;
+  },
+};
+
+function createBaseCompletedPart(): CompletedPart {
+  return { number: 0, id: "" };
+}
+
+export const CompletedPart = {
+  encode(
+    message: CompletedPart,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.number !== 0) {
+      writer.uint32(8).int32(message.number);
+    }
+    if (message.id !== "") {
+      writer.uint32(18).string(message.id);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CompletedPart {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCompletedPart();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.number = reader.int32();
+          break;
+        case 2:
+          message.id = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CompletedPart>): CompletedPart {
+    const message = createBaseCompletedPart();
+    message.number = object.number ?? 0;
+    message.id = object.id ?? "";
+    return message;
+  },
+};
+
+function createBaseStartUploadRequest(): StartUploadRequest {
+  return { upload: undefined };
+}
+
+export const StartUploadRequest = {
+  encode(
+    message: StartUploadRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.upload !== undefined) {
+      MultipartUpload.encode(message.upload, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): StartUploadRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseStartUploadRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.upload = MultipartUpload.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<StartUploadRequest>): StartUploadRequest {
+    const message = createBaseStartUploadRequest();
+    message.upload =
+      object.upload !== undefined && object.upload !== null
+        ? MultipartUpload.fromPartial(object.upload)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseStartUploadResponse(): StartUploadResponse {
+  return { upload: undefined };
+}
+
+export const StartUploadResponse = {
+  encode(
+    message: StartUploadResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.upload !== undefined) {
+      MultipartUpload.encode(message.upload, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): StartUploadResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseStartUploadResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.upload = MultipartUpload.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<StartUploadResponse>): StartUploadResponse {
+    const message = createBaseStartUploadResponse();
+    message.upload =
+      object.upload !== undefined && object.upload !== null
+        ? MultipartUpload.fromPartial(object.upload)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseCompleteUploadRequest(): CompleteUploadRequest {
+  return { upload: undefined };
+}
+
+export const CompleteUploadRequest = {
+  encode(
+    message: CompleteUploadRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.upload !== undefined) {
+      MultipartUpload.encode(message.upload, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): CompleteUploadRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCompleteUploadRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.upload = MultipartUpload.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<CompleteUploadRequest>
+  ): CompleteUploadRequest {
+    const message = createBaseCompleteUploadRequest();
+    message.upload =
+      object.upload !== undefined && object.upload !== null
+        ? MultipartUpload.fromPartial(object.upload)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseCompleteUploadResponse(): CompleteUploadResponse {
+  return { upload: undefined };
+}
+
+export const CompleteUploadResponse = {
+  encode(
+    message: CompleteUploadResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.upload !== undefined) {
+      MultipartUpload.encode(message.upload, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): CompleteUploadResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCompleteUploadResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.upload = MultipartUpload.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<CompleteUploadResponse>
+  ): CompleteUploadResponse {
+    const message = createBaseCompleteUploadResponse();
+    message.upload =
+      object.upload !== undefined && object.upload !== null
+        ? MultipartUpload.fromPartial(object.upload)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseAbortUploadRequest(): AbortUploadRequest {
+  return { upload: undefined };
+}
+
+export const AbortUploadRequest = {
+  encode(
+    message: AbortUploadRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.upload !== undefined) {
+      MultipartUpload.encode(message.upload, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): AbortUploadRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseAbortUploadRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.upload = MultipartUpload.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<AbortUploadRequest>): AbortUploadRequest {
+    const message = createBaseAbortUploadRequest();
+    message.upload =
+      object.upload !== undefined && object.upload !== null
+        ? MultipartUpload.fromPartial(object.upload)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseAbortUploadResponse(): AbortUploadResponse {
+  return {};
+}
+
+export const AbortUploadResponse = {
+  encode(
+    _: AbortUploadResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): AbortUploadResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseAbortUploadResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(_: DeepPartial<AbortUploadResponse>): AbortUploadResponse {
+    const message = createBaseAbortUploadResponse();
+    return message;
+  },
+};
+
+function createBaseMoveUploadRequest(): MoveUploadRequest {
+  return { upload: undefined };
+}
+
+export const MoveUploadRequest = {
+  encode(
+    message: MoveUploadRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.upload !== undefined) {
+      MultipartUpload.encode(message.upload, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): MoveUploadRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseMoveUploadRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.upload = MultipartUpload.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<MoveUploadRequest>): MoveUploadRequest {
+    const message = createBaseMoveUploadRequest();
+    message.upload =
+      object.upload !== undefined && object.upload !== null
+        ? MultipartUpload.fromPartial(object.upload)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseMoveUploadResponse(): MoveUploadResponse {
+  return { file: undefined };
+}
+
+export const MoveUploadResponse = {
+  encode(
+    message: MoveUploadResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.file !== undefined) {
+      File.encode(message.file, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): MoveUploadResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseMoveUploadResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.file = File.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<MoveUploadResponse>): MoveUploadResponse {
+    const message = createBaseMoveUploadResponse();
+    message.file =
+      object.file !== undefined && object.file !== null
+        ? File.fromPartial(object.file)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseUploadRequest(): UploadRequest {
+  return { file: undefined };
+}
+
+export const UploadRequest = {
+  encode(
+    message: UploadRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.file !== undefined) {
+      File.encode(message.file, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UploadRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUploadRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.file = File.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UploadRequest>): UploadRequest {
+    const message = createBaseUploadRequest();
+    message.file =
+      object.file !== undefined && object.file !== null
+        ? File.fromPartial(object.file)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseUploadResponse(): UploadResponse {
+  return { upload: undefined };
+}
+
+export const UploadResponse = {
+  encode(
+    message: UploadResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.upload !== undefined) {
+      Upload.encode(message.upload, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UploadResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUploadResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.upload = Upload.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UploadResponse>): UploadResponse {
+    const message = createBaseUploadResponse();
+    message.upload =
+      object.upload !== undefined && object.upload !== null
+        ? Upload.fromPartial(object.upload)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseGetFileRequest(): GetFileRequest {
+  return { id: "" };
+}
+
+export const GetFileRequest = {
+  encode(
+    message: GetFileRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.id !== "") {
+      writer.uint32(10).string(message.id);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetFileRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetFileRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.id = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetFileRequest>): GetFileRequest {
+    const message = createBaseGetFileRequest();
+    message.id = object.id ?? "";
+    return message;
+  },
+};
+
+function createBaseGetFileResponse(): GetFileResponse {
+  return { file: undefined };
+}
+
+export const GetFileResponse = {
+  encode(
+    message: GetFileResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.file !== undefined) {
+      File.encode(message.file, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetFileResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetFileResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.file = File.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetFileResponse>): GetFileResponse {
+    const message = createBaseGetFileResponse();
+    message.file =
+      object.file !== undefined && object.file !== null
+        ? File.fromPartial(object.file)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseDeleteFileRequest(): DeleteFileRequest {
+  return { file: undefined };
+}
+
+export const DeleteFileRequest = {
+  encode(
+    message: DeleteFileRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.file !== undefined) {
+      File.encode(message.file, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): DeleteFileRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseDeleteFileRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.file = File.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<DeleteFileRequest>): DeleteFileRequest {
+    const message = createBaseDeleteFileRequest();
+    message.file =
+      object.file !== undefined && object.file !== null
+        ? File.fromPartial(object.file)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseDeleteFileResponse(): DeleteFileResponse {
+  return {};
+}
+
+export const DeleteFileResponse = {
+  encode(
+    _: DeleteFileResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): DeleteFileResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseDeleteFileResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(_: DeepPartial<DeleteFileResponse>): DeleteFileResponse {
+    const message = createBaseDeleteFileResponse();
+    return message;
+  },
+};
+
+export type FilesDefinition = typeof FilesDefinition;
+export const FilesDefinition = {
+  name: "Files",
+  fullName: "files.Files",
+  methods: {
+    /**
+     * StartUpload - инициирует процедуру загрузки файла в файловое хранилище.
+     * Используется клиентским приложением для начала загрузки файла
+     * Требуемые параметры: объект `MultipartUpload` с вложенным объектом `File`, в котором
+     * обязательные поля  Name и Size.
+     * Возвращает объект с заполненными полями ID, PartSize, PartURLs, MimeType, Size, UploadID.
+     */
+    startUpload: {
+      name: "StartUpload",
+      requestType: StartUploadRequest,
+      requestStream: false,
+      responseType: StartUploadResponse,
+      responseStream: false,
+      options: {},
+    },
+    /**
+     * CompleteUpload - завершает процедуру загрузку файла
+     * Предполагается, что в объекте, полученном из `StartUpload`, клиент должен заполнить поле
+     * Parts (идентификаторами загруженных блоков (S3 ETAGs)) и передать его в `CompleteUpload`
+     */
+    completeUpload: {
+      name: "CompleteUpload",
+      requestType: CompleteUploadRequest,
+      requestStream: false,
+      responseType: CompleteUploadResponse,
+      responseStream: false,
+      options: {},
+    },
+    /** AbortUpload - прерывает процедуру загрузки файла, все загруженные части файла удаляются их хранилища */
+    abortUpload: {
+      name: "AbortUpload",
+      requestType: AbortUploadRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    /**
+     * MoveUpload - перемещает загруженный файл из временного расположения в постоянное месторасположения.
+     * После перемещение загрузки хранилище выдает новый идентификатор постоянного файла
+     */
+    moveUpload: {
+      name: "MoveUpload",
+      requestType: MoveUploadRequest,
+      requestStream: false,
+      responseType: MoveUploadResponse,
+      responseStream: false,
+      options: {},
+    },
+    /**
+     * Upload - инициация загрузки файла в хранилище. Возвращает объект, содержащий подписанный URL.
+     * Завершение загрузки файла осуществляется выполнением POST-запроса
+     */
+    upload: {
+      name: "Upload",
+      requestType: UploadRequest,
+      requestStream: false,
+      responseType: UploadResponse,
+      responseStream: false,
+      options: {},
+    },
+    /** GetFile - получить информацию о файле (ссылку) по ID */
+    getFile: {
+      name: "GetFile",
+      requestType: GetFileRequest,
+      requestStream: false,
+      responseType: GetFileResponse,
+      responseStream: false,
+      options: {},
+    },
+    /**
+     * DeleteFile - удаляет файл. Если происходит удаление оригинала,
+     * удаляются и все связанные структуры
+     * Возможны следующие ситуации:
+     *  - Удаление оригинального файла. Удаляется файл и все связанные с ним файлы.
+     *  - Удаление связанного файла. Для удаления конкретного файла передается 'ID', 'Type' и 'Name'
+     *  - Удаления связанных файлов конкретного типа (например, все 'thumbnails'). Передается 'ID' и 'Type'
+     */
+    deleteFile: {
+      name: "DeleteFile",
+      requestType: DeleteFileRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+  },
+} as const;
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
diff --git a/clients/files/index.d.ts b/clients/files/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7daae3d8471b23040e46f35625e5b4266ee10b0b
--- /dev/null
+++ b/clients/files/index.d.ts
@@ -0,0 +1,2 @@
+export * from './files';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/files/index.d.ts.map b/clients/files/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..1f64580f3931037e5313efed7af9dcac3617d0bf
--- /dev/null
+++ b/clients/files/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA"}
\ No newline at end of file
diff --git a/clients/files/index.js b/clients/files/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..7c766ad98d9cbe571cbe6cdff6426f94dff418b6
--- /dev/null
+++ b/clients/files/index.js
@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./files"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/files/index.js.map b/clients/files/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..3fef9d4fc40722278aba7d6931ba7465df482b28
--- /dev/null
+++ b/clients/files/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAuB"}
\ No newline at end of file
diff --git a/clients/google/index.d.ts b/clients/google/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..217f8c77a5e60d849e171b1b2cf4d1c184885820
--- /dev/null
+++ b/clients/google/index.d.ts
@@ -0,0 +1,2 @@
+export * as protobuf from './protobuf';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/google/index.d.ts.map b/clients/google/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..f95d5486b65cefc2cd12544c4284d8c510690228
--- /dev/null
+++ b/clients/google/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,YAAY,CAAA"}
\ No newline at end of file
diff --git a/clients/google/index.js b/clients/google/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..8e20c0509c3dca8b0d0d1dbc00d4787e010f0a23
--- /dev/null
+++ b/clients/google/index.js
@@ -0,0 +1,28 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
+    Object.defineProperty(o, "default", { enumerable: true, value: v });
+}) : function(o, v) {
+    o["default"] = v;
+});
+var __importStar = (this && this.__importStar) || function (mod) {
+    if (mod && mod.__esModule) return mod;
+    var result = {};
+    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
+    __setModuleDefault(result, mod);
+    return result;
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.protobuf = void 0;
+exports.protobuf = __importStar(require("./protobuf"));
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/google/index.js.map b/clients/google/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..876b4c9cbbcbfbfb876b080d291b493619aea69c
--- /dev/null
+++ b/clients/google/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uDAAsC"}
\ No newline at end of file
diff --git a/clients/google/protobuf/any.ts b/clients/google/protobuf/any.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8ca454cf8d1805f72ae27c820983cb9070932bad
--- /dev/null
+++ b/clients/google/protobuf/any.ts
@@ -0,0 +1,184 @@
+/* eslint-disable */
+import * as _m0 from "protobufjs/minimal";
+
+/**
+ * `Any` contains an arbitrary serialized protocol buffer message along with a
+ * URL that describes the type of the serialized message.
+ *
+ * Protobuf library provides support to pack/unpack Any values in the form
+ * of utility functions or additional generated methods of the Any type.
+ *
+ * Example 1: Pack and unpack a message in C++.
+ *
+ *     Foo foo = ...;
+ *     Any any;
+ *     any.PackFrom(foo);
+ *     ...
+ *     if (any.UnpackTo(&foo)) {
+ *       ...
+ *     }
+ *
+ * Example 2: Pack and unpack a message in Java.
+ *
+ *     Foo foo = ...;
+ *     Any any = Any.pack(foo);
+ *     ...
+ *     if (any.is(Foo.class)) {
+ *       foo = any.unpack(Foo.class);
+ *     }
+ *
+ * Example 3: Pack and unpack a message in Python.
+ *
+ *     foo = Foo(...)
+ *     any = Any()
+ *     any.Pack(foo)
+ *     ...
+ *     if any.Is(Foo.DESCRIPTOR):
+ *       any.Unpack(foo)
+ *       ...
+ *
+ * Example 4: Pack and unpack a message in Go
+ *
+ *      foo := &pb.Foo{...}
+ *      any, err := anypb.New(foo)
+ *      if err != nil {
+ *        ...
+ *      }
+ *      ...
+ *      foo := &pb.Foo{}
+ *      if err := any.UnmarshalTo(foo); err != nil {
+ *        ...
+ *      }
+ *
+ * The pack methods provided by protobuf library will by default use
+ * 'type.googleapis.com/full.type.name' as the type URL and the unpack
+ * methods only use the fully qualified type name after the last '/'
+ * in the type URL, for example "foo.bar.com/x/y.z" will yield type
+ * name "y.z".
+ *
+ *
+ * JSON
+ *
+ * The JSON representation of an `Any` value uses the regular
+ * representation of the deserialized, embedded message, with an
+ * additional field `@type` which contains the type URL. Example:
+ *
+ *     package google.profile;
+ *     message Person {
+ *       string first_name = 1;
+ *       string last_name = 2;
+ *     }
+ *
+ *     {
+ *       "@type": "type.googleapis.com/google.profile.Person",
+ *       "firstName": <string>,
+ *       "lastName": <string>
+ *     }
+ *
+ * If the embedded message type is well-known and has a custom JSON
+ * representation, that representation will be embedded adding a field
+ * `value` which holds the custom JSON in addition to the `@type`
+ * field. Example (for message [google.protobuf.Duration][]):
+ *
+ *     {
+ *       "@type": "type.googleapis.com/google.protobuf.Duration",
+ *       "value": "1.212s"
+ *     }
+ */
+export interface Any {
+  /**
+   * A URL/resource name that uniquely identifies the type of the serialized
+   * protocol buffer message. This string must contain at least
+   * one "/" character. The last segment of the URL's path must represent
+   * the fully qualified name of the type (as in
+   * `path/google.protobuf.Duration`). The name should be in a canonical form
+   * (e.g., leading "." is not accepted).
+   *
+   * In practice, teams usually precompile into the binary all types that they
+   * expect it to use in the context of Any. However, for URLs which use the
+   * scheme `http`, `https`, or no scheme, one can optionally set up a type
+   * server that maps type URLs to message definitions as follows:
+   *
+   * * If no scheme is provided, `https` is assumed.
+   * * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+   *   value in binary format, or produce an error.
+   * * Applications are allowed to cache lookup results based on the
+   *   URL, or have them precompiled into a binary to avoid any
+   *   lookup. Therefore, binary compatibility needs to be preserved
+   *   on changes to types. (Use versioned type names to manage
+   *   breaking changes.)
+   *
+   * Note: this functionality is not currently available in the official
+   * protobuf release, and it is not used for type URLs beginning with
+   * type.googleapis.com.
+   *
+   * Schemes other than `http`, `https` (or the empty scheme) might be
+   * used with implementation specific semantics.
+   */
+  typeUrl: string;
+  /** Must be a valid serialized protocol buffer of the above specified type. */
+  value: Uint8Array;
+}
+
+function createBaseAny(): Any {
+  return { typeUrl: "", value: new Uint8Array() };
+}
+
+export const Any = {
+  encode(message: Any, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
+    if (message.typeUrl !== "") {
+      writer.uint32(10).string(message.typeUrl);
+    }
+    if (message.value.length !== 0) {
+      writer.uint32(18).bytes(message.value);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Any {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseAny();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.typeUrl = reader.string();
+          break;
+        case 2:
+          message.value = reader.bytes();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Any>): Any {
+    const message = createBaseAny();
+    message.typeUrl = object.typeUrl ?? "";
+    message.value = object.value ?? new Uint8Array();
+    return message;
+  },
+};
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
diff --git a/clients/google/protobuf/empty.ts b/clients/google/protobuf/empty.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bacd7f0663edffb97616b10b2e01d488dd9af6f4
--- /dev/null
+++ b/clients/google/protobuf/empty.ts
@@ -0,0 +1,62 @@
+/* eslint-disable */
+import * as _m0 from "protobufjs/minimal";
+
+/**
+ * A generic empty message that you can re-use to avoid defining duplicated
+ * empty messages in your APIs. A typical example is to use it as the request
+ * or the response type of an API method. For instance:
+ *
+ *     service Foo {
+ *       rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
+ *     }
+ */
+export interface Empty {}
+
+function createBaseEmpty(): Empty {
+  return {};
+}
+
+export const Empty = {
+  encode(_: Empty, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Empty {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseEmpty();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(_: DeepPartial<Empty>): Empty {
+    const message = createBaseEmpty();
+    return message;
+  },
+};
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
diff --git a/clients/google/protobuf/index.d.ts b/clients/google/protobuf/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..24aae570f32375503f26249b532795ceca67314d
--- /dev/null
+++ b/clients/google/protobuf/index.d.ts
@@ -0,0 +1,6 @@
+export * from './struct';
+export * from './any';
+export * from './timestamp';
+export * from './wrappers';
+export * from './empty';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/google/protobuf/index.d.ts.map b/clients/google/protobuf/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..3d6626b6af3b9a395d2a15a9e81c9cd00d99772c
--- /dev/null
+++ b/clients/google/protobuf/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA;AACxB,cAAc,OAAO,CAAA;AACrB,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA"}
\ No newline at end of file
diff --git a/clients/google/protobuf/index.js b/clients/google/protobuf/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..ea6270593ec4545c8cbd256836e4d3b9a704642f
--- /dev/null
+++ b/clients/google/protobuf/index.js
@@ -0,0 +1,22 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./struct"), exports);
+__exportStar(require("./any"), exports);
+__exportStar(require("./timestamp"), exports);
+__exportStar(require("./wrappers"), exports);
+__exportStar(require("./empty"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/google/protobuf/index.js.map b/clients/google/protobuf/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..4bc0bc628324c6504b94e7896f5013f965c72ee8
--- /dev/null
+++ b/clients/google/protobuf/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAwB;AACxB,wCAAqB;AACrB,8CAA2B;AAC3B,6CAA0B;AAC1B,0CAAuB"}
\ No newline at end of file
diff --git a/clients/google/protobuf/struct.ts b/clients/google/protobuf/struct.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ca13189ea0cb9c4cb3db91892963e9a27f43560b
--- /dev/null
+++ b/clients/google/protobuf/struct.ts
@@ -0,0 +1,393 @@
+/* eslint-disable */
+import * as _m0 from "protobufjs/minimal";
+
+/**
+ * `NullValue` is a singleton enumeration to represent the null value for the
+ * `Value` type union.
+ *
+ *  The JSON representation for `NullValue` is JSON `null`.
+ */
+export enum NullValue {
+  /** NULL_VALUE - Null value. */
+  NULL_VALUE = 0,
+  UNRECOGNIZED = -1,
+}
+
+/**
+ * `Struct` represents a structured data value, consisting of fields
+ * which map to dynamically typed values. In some languages, `Struct`
+ * might be supported by a native representation. For example, in
+ * scripting languages like JS a struct is represented as an
+ * object. The details of that representation are described together
+ * with the proto support for the language.
+ *
+ * The JSON representation for `Struct` is JSON object.
+ */
+export interface Struct {
+  /** Unordered map of dynamically typed values. */
+  fields: { [key: string]: any };
+}
+
+export interface Struct_FieldsEntry {
+  key: string;
+  value?: any;
+}
+
+/**
+ * `Value` represents a dynamically typed value which can be either
+ * null, a number, a string, a boolean, a recursive struct value, or a
+ * list of values. A producer of value is expected to set one of these
+ * variants. Absence of any variant indicates an error.
+ *
+ * The JSON representation for `Value` is JSON value.
+ */
+export interface Value {
+  /** Represents a null value. */
+  nullValue: NullValue | undefined;
+  /** Represents a double value. */
+  numberValue: number | undefined;
+  /** Represents a string value. */
+  stringValue: string | undefined;
+  /** Represents a boolean value. */
+  boolValue: boolean | undefined;
+  /** Represents a structured value. */
+  structValue?: { [key: string]: any };
+  /** Represents a repeated `Value`. */
+  listValue?: Array<any>;
+}
+
+/**
+ * `ListValue` is a wrapper around a repeated field of values.
+ *
+ * The JSON representation for `ListValue` is JSON array.
+ */
+export interface ListValue {
+  /** Repeated field of dynamically typed values. */
+  values: any[];
+}
+
+function createBaseStruct(): Struct {
+  return { fields: {} };
+}
+
+export const Struct = {
+  encode(
+    message: Struct,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    Object.entries(message.fields).forEach(([key, value]) => {
+      if (value !== undefined) {
+        Struct_FieldsEntry.encode(
+          { key: key as any, value },
+          writer.uint32(10).fork()
+        ).ldelim();
+      }
+    });
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Struct {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseStruct();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          const entry1 = Struct_FieldsEntry.decode(reader, reader.uint32());
+          if (entry1.value !== undefined) {
+            message.fields[entry1.key] = entry1.value;
+          }
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Struct>): Struct {
+    const message = createBaseStruct();
+    message.fields = Object.entries(object.fields ?? {}).reduce<{
+      [key: string]: any;
+    }>((acc, [key, value]) => {
+      if (value !== undefined) {
+        acc[key] = value;
+      }
+      return acc;
+    }, {});
+    return message;
+  },
+
+  wrap(object: { [key: string]: any } | undefined): Struct {
+    const struct = createBaseStruct();
+    if (object !== undefined) {
+      Object.keys(object).forEach((key) => {
+        struct.fields[key] = object[key];
+      });
+    }
+    return struct;
+  },
+
+  unwrap(message: Struct): { [key: string]: any } {
+    const object: { [key: string]: any } = {};
+    Object.keys(message.fields).forEach((key) => {
+      object[key] = message.fields[key];
+    });
+    return object;
+  },
+};
+
+function createBaseStruct_FieldsEntry(): Struct_FieldsEntry {
+  return { key: "", value: undefined };
+}
+
+export const Struct_FieldsEntry = {
+  encode(
+    message: Struct_FieldsEntry,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.key !== "") {
+      writer.uint32(10).string(message.key);
+    }
+    if (message.value !== undefined) {
+      Value.encode(
+        Value.wrap(message.value),
+        writer.uint32(18).fork()
+      ).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Struct_FieldsEntry {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseStruct_FieldsEntry();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.key = reader.string();
+          break;
+        case 2:
+          message.value = Value.unwrap(Value.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Struct_FieldsEntry>): Struct_FieldsEntry {
+    const message = createBaseStruct_FieldsEntry();
+    message.key = object.key ?? "";
+    message.value = object.value ?? undefined;
+    return message;
+  },
+};
+
+function createBaseValue(): Value {
+  return {
+    nullValue: undefined,
+    numberValue: undefined,
+    stringValue: undefined,
+    boolValue: undefined,
+    structValue: undefined,
+    listValue: undefined,
+  };
+}
+
+export const Value = {
+  encode(message: Value, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
+    if (message.nullValue !== undefined) {
+      writer.uint32(8).int32(message.nullValue);
+    }
+    if (message.numberValue !== undefined) {
+      writer.uint32(17).double(message.numberValue);
+    }
+    if (message.stringValue !== undefined) {
+      writer.uint32(26).string(message.stringValue);
+    }
+    if (message.boolValue !== undefined) {
+      writer.uint32(32).bool(message.boolValue);
+    }
+    if (message.structValue !== undefined) {
+      Struct.encode(
+        Struct.wrap(message.structValue),
+        writer.uint32(42).fork()
+      ).ldelim();
+    }
+    if (message.listValue !== undefined) {
+      ListValue.encode(
+        ListValue.wrap(message.listValue),
+        writer.uint32(50).fork()
+      ).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Value {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseValue();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.nullValue = reader.int32() as any;
+          break;
+        case 2:
+          message.numberValue = reader.double();
+          break;
+        case 3:
+          message.stringValue = reader.string();
+          break;
+        case 4:
+          message.boolValue = reader.bool();
+          break;
+        case 5:
+          message.structValue = Struct.unwrap(
+            Struct.decode(reader, reader.uint32())
+          );
+          break;
+        case 6:
+          message.listValue = ListValue.unwrap(
+            ListValue.decode(reader, reader.uint32())
+          );
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Value>): Value {
+    const message = createBaseValue();
+    message.nullValue = object.nullValue ?? undefined;
+    message.numberValue = object.numberValue ?? undefined;
+    message.stringValue = object.stringValue ?? undefined;
+    message.boolValue = object.boolValue ?? undefined;
+    message.structValue = object.structValue ?? undefined;
+    message.listValue = object.listValue ?? undefined;
+    return message;
+  },
+
+  wrap(value: any): Value {
+    const result = createBaseValue();
+
+    if (value === null) {
+      result.nullValue = NullValue.NULL_VALUE;
+    } else if (typeof value === "boolean") {
+      result.boolValue = value;
+    } else if (typeof value === "number") {
+      result.numberValue = value;
+    } else if (typeof value === "string") {
+      result.stringValue = value;
+    } else if (Array.isArray(value)) {
+      result.listValue = value;
+    } else if (typeof value === "object") {
+      result.structValue = value;
+    } else if (typeof value !== "undefined") {
+      throw new Error("Unsupported any value type: " + typeof value);
+    }
+
+    return result;
+  },
+
+  unwrap(
+    message: Value
+  ): string | number | boolean | Object | null | Array<any> | undefined {
+    if (message?.stringValue !== undefined) {
+      return message.stringValue;
+    } else if (message?.numberValue !== undefined) {
+      return message.numberValue;
+    } else if (message?.boolValue !== undefined) {
+      return message.boolValue;
+    } else if (message?.structValue !== undefined) {
+      return message.structValue;
+    } else if (message?.listValue !== undefined) {
+      return message.listValue;
+    } else if (message?.nullValue !== undefined) {
+      return null;
+    }
+    return undefined;
+  },
+};
+
+function createBaseListValue(): ListValue {
+  return { values: [] };
+}
+
+export const ListValue = {
+  encode(
+    message: ListValue,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.values) {
+      Value.encode(Value.wrap(v!), writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ListValue {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListValue();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.values.push(
+            Value.unwrap(Value.decode(reader, reader.uint32()))
+          );
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListValue>): ListValue {
+    const message = createBaseListValue();
+    message.values = object.values?.map((e) => e) || [];
+    return message;
+  },
+
+  wrap(value: Array<any> | undefined): ListValue {
+    const result = createBaseListValue();
+
+    result.values = value ?? [];
+
+    return result;
+  },
+
+  unwrap(message: ListValue): Array<any> {
+    return message.values;
+  },
+};
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
diff --git a/clients/google/protobuf/timestamp.ts b/clients/google/protobuf/timestamp.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8bd35bdc91740c14a898e57b1db6d9c6d18b1134
--- /dev/null
+++ b/clients/google/protobuf/timestamp.ts
@@ -0,0 +1,201 @@
+/* eslint-disable */
+import Long from "long";
+import * as _m0 from "protobufjs/minimal";
+
+/**
+ * A Timestamp represents a point in time independent of any time zone or local
+ * calendar, encoded as a count of seconds and fractions of seconds at
+ * nanosecond resolution. The count is relative to an epoch at UTC midnight on
+ * January 1, 1970, in the proleptic Gregorian calendar which extends the
+ * Gregorian calendar backwards to year one.
+ *
+ * All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap
+ * second table is needed for interpretation, using a [24-hour linear
+ * smear](https://developers.google.com/time/smear).
+ *
+ * The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By
+ * restricting to that range, we ensure that we can convert to and from [RFC
+ * 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings.
+ *
+ * # Examples
+ *
+ * Example 1: Compute Timestamp from POSIX `time()`.
+ *
+ *     Timestamp timestamp;
+ *     timestamp.set_seconds(time(NULL));
+ *     timestamp.set_nanos(0);
+ *
+ * Example 2: Compute Timestamp from POSIX `gettimeofday()`.
+ *
+ *     struct timeval tv;
+ *     gettimeofday(&tv, NULL);
+ *
+ *     Timestamp timestamp;
+ *     timestamp.set_seconds(tv.tv_sec);
+ *     timestamp.set_nanos(tv.tv_usec * 1000);
+ *
+ * Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
+ *
+ *     FILETIME ft;
+ *     GetSystemTimeAsFileTime(&ft);
+ *     UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
+ *
+ *     // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
+ *     // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
+ *     Timestamp timestamp;
+ *     timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
+ *     timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
+ *
+ * Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
+ *
+ *     long millis = System.currentTimeMillis();
+ *
+ *     Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
+ *         .setNanos((int) ((millis % 1000) * 1000000)).build();
+ *
+ *
+ * Example 5: Compute Timestamp from Java `Instant.now()`.
+ *
+ *     Instant now = Instant.now();
+ *
+ *     Timestamp timestamp =
+ *         Timestamp.newBuilder().setSeconds(now.getEpochSecond())
+ *             .setNanos(now.getNano()).build();
+ *
+ *
+ * Example 6: Compute Timestamp from current time in Python.
+ *
+ *     timestamp = Timestamp()
+ *     timestamp.GetCurrentTime()
+ *
+ * # JSON Mapping
+ *
+ * In JSON format, the Timestamp type is encoded as a string in the
+ * [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the
+ * format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z"
+ * where {year} is always expressed using four digits while {month}, {day},
+ * {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
+ * seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
+ * are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
+ * is required. A proto3 JSON serializer should always use UTC (as indicated by
+ * "Z") when printing the Timestamp type and a proto3 JSON parser should be
+ * able to accept both UTC and other timezones (as indicated by an offset).
+ *
+ * For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
+ * 01:30 UTC on January 15, 2017.
+ *
+ * In JavaScript, one can convert a Date object to this format using the
+ * standard
+ * [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)
+ * method. In Python, a standard `datetime.datetime` object can be converted
+ * to this format using
+ * [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with
+ * the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use
+ * the Joda Time's [`ISODateTimeFormat.dateTime()`](
+ * http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D
+ * ) to obtain a formatter capable of generating timestamps in this format.
+ */
+export interface Timestamp {
+  /**
+   * Represents seconds of UTC time since Unix epoch
+   * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
+   * 9999-12-31T23:59:59Z inclusive.
+   */
+  seconds: number;
+  /**
+   * Non-negative fractions of a second at nanosecond resolution. Negative
+   * second values with fractions must still have non-negative nanos values
+   * that count forward in time. Must be from 0 to 999,999,999
+   * inclusive.
+   */
+  nanos: number;
+}
+
+function createBaseTimestamp(): Timestamp {
+  return { seconds: 0, nanos: 0 };
+}
+
+export const Timestamp = {
+  encode(
+    message: Timestamp,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.seconds !== 0) {
+      writer.uint32(8).int64(message.seconds);
+    }
+    if (message.nanos !== 0) {
+      writer.uint32(16).int32(message.nanos);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Timestamp {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseTimestamp();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.seconds = longToNumber(reader.int64() as Long);
+          break;
+        case 2:
+          message.nanos = reader.int32();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Timestamp>): Timestamp {
+    const message = createBaseTimestamp();
+    message.seconds = object.seconds ?? 0;
+    message.nanos = object.nanos ?? 0;
+    return message;
+  },
+};
+
+declare var self: any | undefined;
+declare var window: any | undefined;
+declare var global: any | undefined;
+var globalThis: any = (() => {
+  if (typeof globalThis !== "undefined") return globalThis;
+  if (typeof self !== "undefined") return self;
+  if (typeof window !== "undefined") return window;
+  if (typeof global !== "undefined") return global;
+  throw "Unable to locate global object";
+})();
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
+
+function longToNumber(long: Long): number {
+  if (long.gt(Number.MAX_SAFE_INTEGER)) {
+    throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER");
+  }
+  return long.toNumber();
+}
+
+if (_m0.util.Long !== Long) {
+  _m0.util.Long = Long as any;
+  _m0.configure();
+}
diff --git a/clients/google/protobuf/wrappers.ts b/clients/google/protobuf/wrappers.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c450c8fad7dc3522d9e15f5eb6fd7763377a44e7
--- /dev/null
+++ b/clients/google/protobuf/wrappers.ts
@@ -0,0 +1,495 @@
+/* eslint-disable */
+import Long from "long";
+import * as _m0 from "protobufjs/minimal";
+
+/**
+ * Wrapper message for `double`.
+ *
+ * The JSON representation for `DoubleValue` is JSON number.
+ */
+export interface DoubleValue {
+  /** The double value. */
+  value: number;
+}
+
+/**
+ * Wrapper message for `float`.
+ *
+ * The JSON representation for `FloatValue` is JSON number.
+ */
+export interface FloatValue {
+  /** The float value. */
+  value: number;
+}
+
+/**
+ * Wrapper message for `int64`.
+ *
+ * The JSON representation for `Int64Value` is JSON string.
+ */
+export interface Int64Value {
+  /** The int64 value. */
+  value: number;
+}
+
+/**
+ * Wrapper message for `uint64`.
+ *
+ * The JSON representation for `UInt64Value` is JSON string.
+ */
+export interface UInt64Value {
+  /** The uint64 value. */
+  value: number;
+}
+
+/**
+ * Wrapper message for `int32`.
+ *
+ * The JSON representation for `Int32Value` is JSON number.
+ */
+export interface Int32Value {
+  /** The int32 value. */
+  value: number;
+}
+
+/**
+ * Wrapper message for `uint32`.
+ *
+ * The JSON representation for `UInt32Value` is JSON number.
+ */
+export interface UInt32Value {
+  /** The uint32 value. */
+  value: number;
+}
+
+/**
+ * Wrapper message for `bool`.
+ *
+ * The JSON representation for `BoolValue` is JSON `true` and `false`.
+ */
+export interface BoolValue {
+  /** The bool value. */
+  value: boolean;
+}
+
+/**
+ * Wrapper message for `string`.
+ *
+ * The JSON representation for `StringValue` is JSON string.
+ */
+export interface StringValue {
+  /** The string value. */
+  value: string;
+}
+
+/**
+ * Wrapper message for `bytes`.
+ *
+ * The JSON representation for `BytesValue` is JSON string.
+ */
+export interface BytesValue {
+  /** The bytes value. */
+  value: Uint8Array;
+}
+
+function createBaseDoubleValue(): DoubleValue {
+  return { value: 0 };
+}
+
+export const DoubleValue = {
+  encode(
+    message: DoubleValue,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.value !== 0) {
+      writer.uint32(9).double(message.value);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): DoubleValue {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseDoubleValue();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.value = reader.double();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<DoubleValue>): DoubleValue {
+    const message = createBaseDoubleValue();
+    message.value = object.value ?? 0;
+    return message;
+  },
+};
+
+function createBaseFloatValue(): FloatValue {
+  return { value: 0 };
+}
+
+export const FloatValue = {
+  encode(
+    message: FloatValue,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.value !== 0) {
+      writer.uint32(13).float(message.value);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): FloatValue {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFloatValue();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.value = reader.float();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<FloatValue>): FloatValue {
+    const message = createBaseFloatValue();
+    message.value = object.value ?? 0;
+    return message;
+  },
+};
+
+function createBaseInt64Value(): Int64Value {
+  return { value: 0 };
+}
+
+export const Int64Value = {
+  encode(
+    message: Int64Value,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.value !== 0) {
+      writer.uint32(8).int64(message.value);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Int64Value {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseInt64Value();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.value = longToNumber(reader.int64() as Long);
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Int64Value>): Int64Value {
+    const message = createBaseInt64Value();
+    message.value = object.value ?? 0;
+    return message;
+  },
+};
+
+function createBaseUInt64Value(): UInt64Value {
+  return { value: 0 };
+}
+
+export const UInt64Value = {
+  encode(
+    message: UInt64Value,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.value !== 0) {
+      writer.uint32(8).uint64(message.value);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UInt64Value {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUInt64Value();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.value = longToNumber(reader.uint64() as Long);
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UInt64Value>): UInt64Value {
+    const message = createBaseUInt64Value();
+    message.value = object.value ?? 0;
+    return message;
+  },
+};
+
+function createBaseInt32Value(): Int32Value {
+  return { value: 0 };
+}
+
+export const Int32Value = {
+  encode(
+    message: Int32Value,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.value !== 0) {
+      writer.uint32(8).int32(message.value);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Int32Value {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseInt32Value();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.value = reader.int32();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Int32Value>): Int32Value {
+    const message = createBaseInt32Value();
+    message.value = object.value ?? 0;
+    return message;
+  },
+};
+
+function createBaseUInt32Value(): UInt32Value {
+  return { value: 0 };
+}
+
+export const UInt32Value = {
+  encode(
+    message: UInt32Value,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.value !== 0) {
+      writer.uint32(8).uint32(message.value);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UInt32Value {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUInt32Value();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.value = reader.uint32();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UInt32Value>): UInt32Value {
+    const message = createBaseUInt32Value();
+    message.value = object.value ?? 0;
+    return message;
+  },
+};
+
+function createBaseBoolValue(): BoolValue {
+  return { value: false };
+}
+
+export const BoolValue = {
+  encode(
+    message: BoolValue,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.value === true) {
+      writer.uint32(8).bool(message.value);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): BoolValue {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseBoolValue();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.value = reader.bool();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<BoolValue>): BoolValue {
+    const message = createBaseBoolValue();
+    message.value = object.value ?? false;
+    return message;
+  },
+};
+
+function createBaseStringValue(): StringValue {
+  return { value: "" };
+}
+
+export const StringValue = {
+  encode(
+    message: StringValue,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.value !== "") {
+      writer.uint32(10).string(message.value);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): StringValue {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseStringValue();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.value = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<StringValue>): StringValue {
+    const message = createBaseStringValue();
+    message.value = object.value ?? "";
+    return message;
+  },
+};
+
+function createBaseBytesValue(): BytesValue {
+  return { value: new Uint8Array() };
+}
+
+export const BytesValue = {
+  encode(
+    message: BytesValue,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.value.length !== 0) {
+      writer.uint32(10).bytes(message.value);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): BytesValue {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseBytesValue();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.value = reader.bytes();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<BytesValue>): BytesValue {
+    const message = createBaseBytesValue();
+    message.value = object.value ?? new Uint8Array();
+    return message;
+  },
+};
+
+declare var self: any | undefined;
+declare var window: any | undefined;
+declare var global: any | undefined;
+var globalThis: any = (() => {
+  if (typeof globalThis !== "undefined") return globalThis;
+  if (typeof self !== "undefined") return self;
+  if (typeof window !== "undefined") return window;
+  if (typeof global !== "undefined") return global;
+  throw "Unable to locate global object";
+})();
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
+
+function longToNumber(long: Long): number {
+  if (long.gt(Number.MAX_SAFE_INTEGER)) {
+    throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER");
+  }
+  return long.toNumber();
+}
+
+if (_m0.util.Long !== Long) {
+  _m0.util.Long = Long as any;
+  _m0.configure();
+}
diff --git a/clients/images/images.ts b/clients/images/images.ts
new file mode 100644
index 0000000000000000000000000000000000000000..88e33ac4af70966e9fed8a75b62555e898c69cdd
--- /dev/null
+++ b/clients/images/images.ts
@@ -0,0 +1,255 @@
+/* eslint-disable */
+import { File } from "../files/files";
+import * as _m0 from "protobufjs/minimal";
+
+export interface Param {
+  op: string;
+  value: string[];
+}
+
+export interface GetRequest {
+  source?: File;
+  opts?: GetRequest_GetOptions;
+}
+
+export interface GetRequest_GetOptions {
+  params: Param[];
+}
+
+export interface GetResponse {
+  result?: File;
+}
+
+function createBaseParam(): Param {
+  return { op: "", value: [] };
+}
+
+export const Param = {
+  encode(message: Param, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
+    if (message.op !== "") {
+      writer.uint32(10).string(message.op);
+    }
+    for (const v of message.value) {
+      writer.uint32(18).string(v!);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Param {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseParam();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.op = reader.string();
+          break;
+        case 2:
+          message.value.push(reader.string());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Param>): Param {
+    const message = createBaseParam();
+    message.op = object.op ?? "";
+    message.value = object.value?.map((e) => e) || [];
+    return message;
+  },
+};
+
+function createBaseGetRequest(): GetRequest {
+  return { source: undefined, opts: undefined };
+}
+
+export const GetRequest = {
+  encode(
+    message: GetRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.source !== undefined) {
+      File.encode(message.source, writer.uint32(10).fork()).ldelim();
+    }
+    if (message.opts !== undefined) {
+      GetRequest_GetOptions.encode(
+        message.opts,
+        writer.uint32(18).fork()
+      ).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.source = File.decode(reader, reader.uint32());
+          break;
+        case 2:
+          message.opts = GetRequest_GetOptions.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetRequest>): GetRequest {
+    const message = createBaseGetRequest();
+    message.source =
+      object.source !== undefined && object.source !== null
+        ? File.fromPartial(object.source)
+        : undefined;
+    message.opts =
+      object.opts !== undefined && object.opts !== null
+        ? GetRequest_GetOptions.fromPartial(object.opts)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseGetRequest_GetOptions(): GetRequest_GetOptions {
+  return { params: [] };
+}
+
+export const GetRequest_GetOptions = {
+  encode(
+    message: GetRequest_GetOptions,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.params) {
+      Param.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): GetRequest_GetOptions {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetRequest_GetOptions();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.params.push(Param.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<GetRequest_GetOptions>
+  ): GetRequest_GetOptions {
+    const message = createBaseGetRequest_GetOptions();
+    message.params = object.params?.map((e) => Param.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseGetResponse(): GetResponse {
+  return { result: undefined };
+}
+
+export const GetResponse = {
+  encode(
+    message: GetResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.result !== undefined) {
+      File.encode(message.result, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.result = File.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetResponse>): GetResponse {
+    const message = createBaseGetResponse();
+    message.result =
+      object.result !== undefined && object.result !== null
+        ? File.fromPartial(object.result)
+        : undefined;
+    return message;
+  },
+};
+
+/** ImageService - сервис для обработки изображений */
+export type ImagesDefinition = typeof ImagesDefinition;
+export const ImagesDefinition = {
+  name: "Images",
+  fullName: "images.Images",
+  methods: {
+    /**
+     * Get - к файлу, идентификатор которого передан в запросе, применяются параметры.
+     * Может быть передано несколько параметров, порядок учитывается при обработке
+     * Допустимые операции:
+     *  - crop (ширина, высота)
+     *  - fit (ширина, высота)
+     *  - resize (ширина, высота)
+     *  - format (один из форматов [ png, jpeg, jpg, gif ]
+     * Возвращает объект File с заполненным полем File.URL
+     */
+    get: {
+      name: "Get",
+      requestType: GetRequest,
+      requestStream: false,
+      responseType: GetResponse,
+      responseStream: false,
+      options: {},
+    },
+  },
+} as const;
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
diff --git a/clients/images/index.d.ts b/clients/images/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..eecf6e3dc3bcb27ef50567e950007a630717ba5e
--- /dev/null
+++ b/clients/images/index.d.ts
@@ -0,0 +1,2 @@
+export * from './images';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/images/index.d.ts.map b/clients/images/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..d68da9bfd6c9e0e766776d648d711c343fde236c
--- /dev/null
+++ b/clients/images/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA"}
\ No newline at end of file
diff --git a/clients/images/index.js b/clients/images/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..07161b3137036a5d53cd2bb38bd118fb7a38dfb9
--- /dev/null
+++ b/clients/images/index.js
@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./images"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/images/index.js.map b/clients/images/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..9a82574a46940f84df0cf1940e8c3b0bab8d91ef
--- /dev/null
+++ b/clients/images/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAwB"}
\ No newline at end of file
diff --git a/clients/index.d.ts b/clients/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..14ff7051c5c37a0b902059f551ff761f7eafa883
--- /dev/null
+++ b/clients/index.d.ts
@@ -0,0 +1,21 @@
+export * as collaborators from './collaborators';
+export * as collections from './collections';
+export * as common from './common';
+export * as delivery from './delivery';
+export * as environments from './environments';
+export * as extensions from './extensions';
+export * as files from './files';
+export * as google from './google';
+export * as images from './images';
+export * as invitations from './invitations';
+export * as items from './items';
+export * as locales from './locales';
+export * as members from './members';
+export * as organizations from './organizations';
+export * as references from './references';
+export * as roles from './roles';
+export * as spaces from './spaces';
+export * as status from './status';
+export * as users from './users';
+export * as versions from './versions';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/index.d.ts.map b/clients/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..c769cccf229235ed7c17ba5dfee9c7f987eec4d5
--- /dev/null
+++ b/clients/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,aAAa,MAAM,iBAAiB,CAAA;AAChD,OAAO,KAAK,WAAW,MAAM,eAAe,CAAA;AAC5C,OAAO,KAAK,MAAM,MAAM,UAAU,CAAA;AAClC,OAAO,KAAK,QAAQ,MAAM,YAAY,CAAA;AACtC,OAAO,KAAK,YAAY,MAAM,gBAAgB,CAAA;AAC9C,OAAO,KAAK,UAAU,MAAM,cAAc,CAAA;AAC1C,OAAO,KAAK,KAAK,MAAM,SAAS,CAAA;AAChC,OAAO,KAAK,MAAM,MAAM,UAAU,CAAA;AAClC,OAAO,KAAK,MAAM,MAAM,UAAU,CAAA;AAClC,OAAO,KAAK,WAAW,MAAM,eAAe,CAAA;AAC5C,OAAO,KAAK,KAAK,MAAM,SAAS,CAAA;AAChC,OAAO,KAAK,OAAO,MAAM,WAAW,CAAA;AACpC,OAAO,KAAK,OAAO,MAAM,WAAW,CAAA;AACpC,OAAO,KAAK,aAAa,MAAM,iBAAiB,CAAA;AAChD,OAAO,KAAK,UAAU,MAAM,cAAc,CAAA;AAC1C,OAAO,KAAK,KAAK,MAAM,SAAS,CAAA;AAChC,OAAO,KAAK,MAAM,MAAM,UAAU,CAAA;AAClC,OAAO,KAAK,MAAM,MAAM,UAAU,CAAA;AAClC,OAAO,KAAK,KAAK,MAAM,SAAS,CAAA;AAChC,OAAO,KAAK,QAAQ,MAAM,YAAY,CAAA"}
\ No newline at end of file
diff --git a/clients/index.js b/clients/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..95ce69cd0ef793c3fce13ed73e7af8f167ab2e2e
--- /dev/null
+++ b/clients/index.js
@@ -0,0 +1,47 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
+    Object.defineProperty(o, "default", { enumerable: true, value: v });
+}) : function(o, v) {
+    o["default"] = v;
+});
+var __importStar = (this && this.__importStar) || function (mod) {
+    if (mod && mod.__esModule) return mod;
+    var result = {};
+    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
+    __setModuleDefault(result, mod);
+    return result;
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.versions = exports.users = exports.status = exports.spaces = exports.roles = exports.references = exports.organizations = exports.members = exports.locales = exports.items = exports.invitations = exports.images = exports.google = exports.files = exports.extensions = exports.environments = exports.delivery = exports.common = exports.collections = exports.collaborators = void 0;
+exports.collaborators = __importStar(require("./collaborators"));
+exports.collections = __importStar(require("./collections"));
+exports.common = __importStar(require("./common"));
+exports.delivery = __importStar(require("./delivery"));
+exports.environments = __importStar(require("./environments"));
+exports.extensions = __importStar(require("./extensions"));
+exports.files = __importStar(require("./files"));
+exports.google = __importStar(require("./google"));
+exports.images = __importStar(require("./images"));
+exports.invitations = __importStar(require("./invitations"));
+exports.items = __importStar(require("./items"));
+exports.locales = __importStar(require("./locales"));
+exports.members = __importStar(require("./members"));
+exports.organizations = __importStar(require("./organizations"));
+exports.references = __importStar(require("./references"));
+exports.roles = __importStar(require("./roles"));
+exports.spaces = __importStar(require("./spaces"));
+exports.status = __importStar(require("./status"));
+exports.users = __importStar(require("./users"));
+exports.versions = __importStar(require("./versions"));
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/index.js.map b/clients/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..26998b9ab3cfbcecdb27b91df796a334427f974f
--- /dev/null
+++ b/clients/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,iEAAgD;AAChD,6DAA4C;AAC5C,mDAAkC;AAClC,uDAAsC;AACtC,+DAA8C;AAC9C,2DAA0C;AAC1C,iDAAgC;AAChC,mDAAkC;AAClC,mDAAkC;AAClC,6DAA4C;AAC5C,iDAAgC;AAChC,qDAAoC;AACpC,qDAAoC;AACpC,iEAAgD;AAChD,2DAA0C;AAC1C,iDAAgC;AAChC,mDAAkC;AAClC,mDAAkC;AAClC,iDAAgC;AAChC,uDAAsC"}
\ No newline at end of file
diff --git a/clients/invitations/index.d.ts b/clients/invitations/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..563c76f0f2ea828b557299629cc44458855459c2
--- /dev/null
+++ b/clients/invitations/index.d.ts
@@ -0,0 +1,2 @@
+export * from './invitations';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/invitations/index.d.ts.map b/clients/invitations/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..5b507a9ad2ce48aebf1a743e716198f48cf9ad30
--- /dev/null
+++ b/clients/invitations/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAA"}
\ No newline at end of file
diff --git a/clients/invitations/index.js b/clients/invitations/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..5d15175aacf027615eb75187a98dc2916c3d4d73
--- /dev/null
+++ b/clients/invitations/index.js
@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./invitations"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/invitations/index.js.map b/clients/invitations/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..64c493ecdc723183734cd145ce14a34452cc0391
--- /dev/null
+++ b/clients/invitations/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA6B"}
\ No newline at end of file
diff --git a/clients/invitations/invitations.ts b/clients/invitations/invitations.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f2fa25afaf77ad61002be58539ddf3fb91c7bccd
--- /dev/null
+++ b/clients/invitations/invitations.ts
@@ -0,0 +1,969 @@
+/* eslint-disable */
+import { Timestamp } from "../google/protobuf/timestamp";
+import Long from "long";
+import { Empty } from "../google/protobuf/empty";
+import * as _m0 from "protobufjs/minimal";
+import { BoolValue } from "../google/protobuf/wrappers";
+
+export interface Invitation {
+  id: string;
+  email: string;
+  orgId: string;
+  spaceId: string;
+  ownerId: string;
+  role: string;
+  createdAt?: Timestamp;
+  validUntil?: Timestamp;
+}
+
+export interface Filter {
+  id: string[];
+  email: string[];
+  orgId: string[];
+  spaceId: string[];
+  ownerId: string[];
+  role: string[];
+}
+
+export interface FindOptions {
+  sort: string[];
+  pageNum: number;
+  pageSize: number;
+}
+
+export interface CreateRequest {
+  invitation?: Invitation;
+}
+
+export interface CreateResponse {
+  invitation?: Invitation;
+}
+
+export interface GetRequest {
+  invitationId: string;
+}
+
+export interface GetResponse {
+  invitation?: Invitation;
+}
+
+export interface UpdateRequest {
+  invitationId: string;
+  /** Флаг отправки приглашения */
+  sent?: boolean;
+  /** Флаг принятия приглашения */
+  pending?: boolean;
+  /** Время отправки приглашения */
+  sentAt?: Timestamp;
+  /** Время до которого приглашение действует */
+  validUntil?: Timestamp;
+}
+
+export interface UpdateInvitationResponse {}
+
+export interface AcceptRequest {
+  invitationId: string;
+  userId: string;
+}
+
+export interface AcceptInvitationResponse {}
+
+export interface FindRequest {
+  filter?: Filter;
+  opts?: FindOptions;
+}
+
+export interface FindResponse {
+  invitations: Invitation[];
+  total: number;
+}
+
+export interface DeleteRequest {
+  invitationId: string;
+}
+
+export interface DeleteSpaceInvitationResponse {}
+
+function createBaseInvitation(): Invitation {
+  return {
+    id: "",
+    email: "",
+    orgId: "",
+    spaceId: "",
+    ownerId: "",
+    role: "",
+    createdAt: undefined,
+    validUntil: undefined,
+  };
+}
+
+export const Invitation = {
+  encode(
+    message: Invitation,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.id !== "") {
+      writer.uint32(10).string(message.id);
+    }
+    if (message.email !== "") {
+      writer.uint32(18).string(message.email);
+    }
+    if (message.orgId !== "") {
+      writer.uint32(26).string(message.orgId);
+    }
+    if (message.spaceId !== "") {
+      writer.uint32(34).string(message.spaceId);
+    }
+    if (message.ownerId !== "") {
+      writer.uint32(42).string(message.ownerId);
+    }
+    if (message.role !== "") {
+      writer.uint32(50).string(message.role);
+    }
+    if (message.createdAt !== undefined) {
+      Timestamp.encode(message.createdAt, writer.uint32(58).fork()).ldelim();
+    }
+    if (message.validUntil !== undefined) {
+      Timestamp.encode(message.validUntil, writer.uint32(66).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Invitation {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseInvitation();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.id = reader.string();
+          break;
+        case 2:
+          message.email = reader.string();
+          break;
+        case 3:
+          message.orgId = reader.string();
+          break;
+        case 4:
+          message.spaceId = reader.string();
+          break;
+        case 5:
+          message.ownerId = reader.string();
+          break;
+        case 6:
+          message.role = reader.string();
+          break;
+        case 7:
+          message.createdAt = Timestamp.decode(reader, reader.uint32());
+          break;
+        case 8:
+          message.validUntil = Timestamp.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Invitation>): Invitation {
+    const message = createBaseInvitation();
+    message.id = object.id ?? "";
+    message.email = object.email ?? "";
+    message.orgId = object.orgId ?? "";
+    message.spaceId = object.spaceId ?? "";
+    message.ownerId = object.ownerId ?? "";
+    message.role = object.role ?? "";
+    message.createdAt =
+      object.createdAt !== undefined && object.createdAt !== null
+        ? Timestamp.fromPartial(object.createdAt)
+        : undefined;
+    message.validUntil =
+      object.validUntil !== undefined && object.validUntil !== null
+        ? Timestamp.fromPartial(object.validUntil)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseFilter(): Filter {
+  return { id: [], email: [], orgId: [], spaceId: [], ownerId: [], role: [] };
+}
+
+export const Filter = {
+  encode(
+    message: Filter,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.id) {
+      writer.uint32(10).string(v!);
+    }
+    for (const v of message.email) {
+      writer.uint32(18).string(v!);
+    }
+    for (const v of message.orgId) {
+      writer.uint32(26).string(v!);
+    }
+    for (const v of message.spaceId) {
+      writer.uint32(34).string(v!);
+    }
+    for (const v of message.ownerId) {
+      writer.uint32(42).string(v!);
+    }
+    for (const v of message.role) {
+      writer.uint32(50).string(v!);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Filter {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFilter();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.id.push(reader.string());
+          break;
+        case 2:
+          message.email.push(reader.string());
+          break;
+        case 3:
+          message.orgId.push(reader.string());
+          break;
+        case 4:
+          message.spaceId.push(reader.string());
+          break;
+        case 5:
+          message.ownerId.push(reader.string());
+          break;
+        case 6:
+          message.role.push(reader.string());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Filter>): Filter {
+    const message = createBaseFilter();
+    message.id = object.id?.map((e) => e) || [];
+    message.email = object.email?.map((e) => e) || [];
+    message.orgId = object.orgId?.map((e) => e) || [];
+    message.spaceId = object.spaceId?.map((e) => e) || [];
+    message.ownerId = object.ownerId?.map((e) => e) || [];
+    message.role = object.role?.map((e) => e) || [];
+    return message;
+  },
+};
+
+function createBaseFindOptions(): FindOptions {
+  return { sort: [], pageNum: 0, pageSize: 0 };
+}
+
+export const FindOptions = {
+  encode(
+    message: FindOptions,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.sort) {
+      writer.uint32(10).string(v!);
+    }
+    if (message.pageNum !== 0) {
+      writer.uint32(16).int32(message.pageNum);
+    }
+    if (message.pageSize !== 0) {
+      writer.uint32(24).int32(message.pageSize);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): FindOptions {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFindOptions();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.sort.push(reader.string());
+          break;
+        case 2:
+          message.pageNum = reader.int32();
+          break;
+        case 3:
+          message.pageSize = reader.int32();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<FindOptions>): FindOptions {
+    const message = createBaseFindOptions();
+    message.sort = object.sort?.map((e) => e) || [];
+    message.pageNum = object.pageNum ?? 0;
+    message.pageSize = object.pageSize ?? 0;
+    return message;
+  },
+};
+
+function createBaseCreateRequest(): CreateRequest {
+  return { invitation: undefined };
+}
+
+export const CreateRequest = {
+  encode(
+    message: CreateRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.invitation !== undefined) {
+      Invitation.encode(message.invitation, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CreateRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCreateRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.invitation = Invitation.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CreateRequest>): CreateRequest {
+    const message = createBaseCreateRequest();
+    message.invitation =
+      object.invitation !== undefined && object.invitation !== null
+        ? Invitation.fromPartial(object.invitation)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseCreateResponse(): CreateResponse {
+  return { invitation: undefined };
+}
+
+export const CreateResponse = {
+  encode(
+    message: CreateResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.invitation !== undefined) {
+      Invitation.encode(message.invitation, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CreateResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCreateResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.invitation = Invitation.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CreateResponse>): CreateResponse {
+    const message = createBaseCreateResponse();
+    message.invitation =
+      object.invitation !== undefined && object.invitation !== null
+        ? Invitation.fromPartial(object.invitation)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseGetRequest(): GetRequest {
+  return { invitationId: "" };
+}
+
+export const GetRequest = {
+  encode(
+    message: GetRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.invitationId !== "") {
+      writer.uint32(10).string(message.invitationId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.invitationId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetRequest>): GetRequest {
+    const message = createBaseGetRequest();
+    message.invitationId = object.invitationId ?? "";
+    return message;
+  },
+};
+
+function createBaseGetResponse(): GetResponse {
+  return { invitation: undefined };
+}
+
+export const GetResponse = {
+  encode(
+    message: GetResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.invitation !== undefined) {
+      Invitation.encode(message.invitation, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.invitation = Invitation.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetResponse>): GetResponse {
+    const message = createBaseGetResponse();
+    message.invitation =
+      object.invitation !== undefined && object.invitation !== null
+        ? Invitation.fromPartial(object.invitation)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseUpdateRequest(): UpdateRequest {
+  return {
+    invitationId: "",
+    sent: undefined,
+    pending: undefined,
+    sentAt: undefined,
+    validUntil: undefined,
+  };
+}
+
+export const UpdateRequest = {
+  encode(
+    message: UpdateRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.invitationId !== "") {
+      writer.uint32(10).string(message.invitationId);
+    }
+    if (message.sent !== undefined) {
+      BoolValue.encode(
+        { value: message.sent! },
+        writer.uint32(18).fork()
+      ).ldelim();
+    }
+    if (message.pending !== undefined) {
+      BoolValue.encode(
+        { value: message.pending! },
+        writer.uint32(26).fork()
+      ).ldelim();
+    }
+    if (message.sentAt !== undefined) {
+      Timestamp.encode(message.sentAt, writer.uint32(34).fork()).ldelim();
+    }
+    if (message.validUntil !== undefined) {
+      Timestamp.encode(message.validUntil, writer.uint32(42).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UpdateRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUpdateRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.invitationId = reader.string();
+          break;
+        case 2:
+          message.sent = BoolValue.decode(reader, reader.uint32()).value;
+          break;
+        case 3:
+          message.pending = BoolValue.decode(reader, reader.uint32()).value;
+          break;
+        case 4:
+          message.sentAt = Timestamp.decode(reader, reader.uint32());
+          break;
+        case 5:
+          message.validUntil = Timestamp.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UpdateRequest>): UpdateRequest {
+    const message = createBaseUpdateRequest();
+    message.invitationId = object.invitationId ?? "";
+    message.sent = object.sent ?? undefined;
+    message.pending = object.pending ?? undefined;
+    message.sentAt =
+      object.sentAt !== undefined && object.sentAt !== null
+        ? Timestamp.fromPartial(object.sentAt)
+        : undefined;
+    message.validUntil =
+      object.validUntil !== undefined && object.validUntil !== null
+        ? Timestamp.fromPartial(object.validUntil)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseUpdateInvitationResponse(): UpdateInvitationResponse {
+  return {};
+}
+
+export const UpdateInvitationResponse = {
+  encode(
+    _: UpdateInvitationResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): UpdateInvitationResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUpdateInvitationResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    _: DeepPartial<UpdateInvitationResponse>
+  ): UpdateInvitationResponse {
+    const message = createBaseUpdateInvitationResponse();
+    return message;
+  },
+};
+
+function createBaseAcceptRequest(): AcceptRequest {
+  return { invitationId: "", userId: "" };
+}
+
+export const AcceptRequest = {
+  encode(
+    message: AcceptRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.invitationId !== "") {
+      writer.uint32(10).string(message.invitationId);
+    }
+    if (message.userId !== "") {
+      writer.uint32(18).string(message.userId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): AcceptRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseAcceptRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.invitationId = reader.string();
+          break;
+        case 2:
+          message.userId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<AcceptRequest>): AcceptRequest {
+    const message = createBaseAcceptRequest();
+    message.invitationId = object.invitationId ?? "";
+    message.userId = object.userId ?? "";
+    return message;
+  },
+};
+
+function createBaseAcceptInvitationResponse(): AcceptInvitationResponse {
+  return {};
+}
+
+export const AcceptInvitationResponse = {
+  encode(
+    _: AcceptInvitationResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): AcceptInvitationResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseAcceptInvitationResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    _: DeepPartial<AcceptInvitationResponse>
+  ): AcceptInvitationResponse {
+    const message = createBaseAcceptInvitationResponse();
+    return message;
+  },
+};
+
+function createBaseFindRequest(): FindRequest {
+  return { filter: undefined, opts: undefined };
+}
+
+export const FindRequest = {
+  encode(
+    message: FindRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.filter !== undefined) {
+      Filter.encode(message.filter, writer.uint32(10).fork()).ldelim();
+    }
+    if (message.opts !== undefined) {
+      FindOptions.encode(message.opts, writer.uint32(18).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): FindRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFindRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.filter = Filter.decode(reader, reader.uint32());
+          break;
+        case 2:
+          message.opts = FindOptions.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<FindRequest>): FindRequest {
+    const message = createBaseFindRequest();
+    message.filter =
+      object.filter !== undefined && object.filter !== null
+        ? Filter.fromPartial(object.filter)
+        : undefined;
+    message.opts =
+      object.opts !== undefined && object.opts !== null
+        ? FindOptions.fromPartial(object.opts)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseFindResponse(): FindResponse {
+  return { invitations: [], total: 0 };
+}
+
+export const FindResponse = {
+  encode(
+    message: FindResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.invitations) {
+      Invitation.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    if (message.total !== 0) {
+      writer.uint32(16).int64(message.total);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): FindResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFindResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.invitations.push(Invitation.decode(reader, reader.uint32()));
+          break;
+        case 2:
+          message.total = longToNumber(reader.int64() as Long);
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<FindResponse>): FindResponse {
+    const message = createBaseFindResponse();
+    message.invitations =
+      object.invitations?.map((e) => Invitation.fromPartial(e)) || [];
+    message.total = object.total ?? 0;
+    return message;
+  },
+};
+
+function createBaseDeleteRequest(): DeleteRequest {
+  return { invitationId: "" };
+}
+
+export const DeleteRequest = {
+  encode(
+    message: DeleteRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.invitationId !== "") {
+      writer.uint32(10).string(message.invitationId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): DeleteRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseDeleteRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.invitationId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<DeleteRequest>): DeleteRequest {
+    const message = createBaseDeleteRequest();
+    message.invitationId = object.invitationId ?? "";
+    return message;
+  },
+};
+
+function createBaseDeleteSpaceInvitationResponse(): DeleteSpaceInvitationResponse {
+  return {};
+}
+
+export const DeleteSpaceInvitationResponse = {
+  encode(
+    _: DeleteSpaceInvitationResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): DeleteSpaceInvitationResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseDeleteSpaceInvitationResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    _: DeepPartial<DeleteSpaceInvitationResponse>
+  ): DeleteSpaceInvitationResponse {
+    const message = createBaseDeleteSpaceInvitationResponse();
+    return message;
+  },
+};
+
+export type InvitationsDefinition = typeof InvitationsDefinition;
+export const InvitationsDefinition = {
+  name: "Invitations",
+  fullName: "content.invitations.Invitations",
+  methods: {
+    create: {
+      name: "Create",
+      requestType: CreateRequest,
+      requestStream: false,
+      responseType: CreateResponse,
+      responseStream: false,
+      options: {},
+    },
+    /** Получить данные о приглашении */
+    get: {
+      name: "Get",
+      requestType: GetRequest,
+      requestStream: false,
+      responseType: GetResponse,
+      responseStream: false,
+      options: {},
+    },
+    /** Принять приглашение */
+    accept: {
+      name: "Accept",
+      requestType: AcceptRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    /** Получить список приглашений для пространства */
+    find: {
+      name: "Find",
+      requestType: FindRequest,
+      requestStream: false,
+      responseType: FindResponse,
+      responseStream: false,
+      options: {},
+    },
+    /** Удалить приглашение */
+    delete: {
+      name: "Delete",
+      requestType: DeleteRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+  },
+} as const;
+
+declare var self: any | undefined;
+declare var window: any | undefined;
+declare var global: any | undefined;
+var globalThis: any = (() => {
+  if (typeof globalThis !== "undefined") return globalThis;
+  if (typeof self !== "undefined") return self;
+  if (typeof window !== "undefined") return window;
+  if (typeof global !== "undefined") return global;
+  throw "Unable to locate global object";
+})();
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
+
+function longToNumber(long: Long): number {
+  if (long.gt(Number.MAX_SAFE_INTEGER)) {
+    throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER");
+  }
+  return long.toNumber();
+}
+
+if (_m0.util.Long !== Long) {
+  _m0.util.Long = Long as any;
+  _m0.configure();
+}
diff --git a/clients/items/index.d.ts b/clients/items/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..07349bf19c28aad7a575587bafd8aa7f79fa6940
--- /dev/null
+++ b/clients/items/index.d.ts
@@ -0,0 +1,2 @@
+export * from './items';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/items/index.d.ts.map b/clients/items/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..1f64580f3931037e5313efed7af9dcac3617d0bf
--- /dev/null
+++ b/clients/items/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA"}
\ No newline at end of file
diff --git a/clients/items/index.js b/clients/items/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..c7d54a9b631eacce73720e223c253d52eb67992a
--- /dev/null
+++ b/clients/items/index.js
@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./items"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/items/index.js.map b/clients/items/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..3fef9d4fc40722278aba7d6931ba7465df482b28
--- /dev/null
+++ b/clients/items/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAuB"}
\ No newline at end of file
diff --git a/clients/items/items.ts b/clients/items/items.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b0f957134e2b65231f10a33986ee5dd5bb44b620
--- /dev/null
+++ b/clients/items/items.ts
@@ -0,0 +1,2948 @@
+/* eslint-disable */
+import { Timestamp } from "../google/protobuf/timestamp";
+import {
+  FindOptions as FindOptions1,
+  Filter as Filter2,
+  Error_BadRequest_FieldViolation,
+} from "../common/common";
+import { Empty } from "../google/protobuf/empty";
+import * as _m0 from "protobufjs/minimal";
+import { Struct } from "../google/protobuf/struct";
+
+/**
+ * # Items
+ *
+ * API Сервиса работы с пользовательским записями (Items)
+ *
+ * Предоставляет доступ к записям пользовательских коллекций
+ */
+
+export interface Error {
+  /** Сообщение об ошибке */
+  message: string;
+  /** Поле в котором произошла ошибка */
+  field: string;
+}
+
+export interface DecodeError {
+  errors: Error[];
+}
+
+export interface ValidationError {
+  errors: Error[];
+}
+
+export interface ModificationError {
+  errors: Error[];
+}
+
+export interface Permissions {
+  edit: boolean;
+  archive: boolean;
+  publish: boolean;
+  softDelete: boolean;
+  hardDelete: boolean;
+}
+
+/** Пользовательская запись */
+export interface Item {
+  id: string;
+  spaceId: string;
+  envId: string;
+  collectionId: string;
+  state: Item_State;
+  /** дата создания текущей ревизии */
+  createdRevAt?: Timestamp;
+  /** id пользователя создавшего первую ревизию */
+  createdBy: string;
+  /** дата создания первой ревизии */
+  createdAt?: Timestamp;
+  /** id пользователя обновившего текущую ревизию */
+  updatedBy: string;
+  /** дата обновления текущей ревизии */
+  updatedAt?: Timestamp;
+  data?: { [key: string]: any };
+  translations: { [key: string]: { [key: string]: any } };
+  revisionId: string;
+  publishedAt?: Timestamp;
+  publishedBy: string;
+  archivedAt?: Timestamp;
+  archivedBy: string;
+  locale: string;
+  deleted: boolean;
+  hidden: boolean;
+  template: boolean;
+  permissions?: Permissions;
+}
+
+export enum Item_State {
+  DRAFT = 0,
+  PUBLISHED = 1,
+  CHANGED = 2,
+  ARCHIVED = 3,
+  UNRECOGNIZED = -1,
+}
+
+export interface Item_TranslationsEntry {
+  key: string;
+  value?: { [key: string]: any };
+}
+
+export interface Filter {
+  /** Список ID записей кото */
+  id: string[];
+  /** Список фильтров */
+  data: Filter2[];
+  /** Список выражений для фильтрации */
+  q: string[];
+}
+
+export interface CreateOptions {
+  updateAttrs: boolean;
+}
+
+export interface FindOptions {
+  options?: FindOptions1;
+  deleted: boolean;
+  regular: boolean;
+  hidden: boolean;
+  templates: boolean;
+}
+
+export interface UpdateOptions {
+  updateAttrs: boolean;
+}
+
+export interface GetPublishedOptions {
+  localeId: string;
+}
+
+export interface DeleteOptions {
+  erase: boolean;
+}
+
+export interface PublishOptions {
+  updateAttrs: boolean;
+}
+
+export interface FindPublishedOptions {
+  options?: FindOptions1;
+  localeId: string;
+  regular: boolean;
+  hidden: boolean;
+  templates: boolean;
+}
+
+export interface FindArchivedOptions {
+  options?: FindOptions1;
+}
+
+export interface ListRevisionsOptions {
+  options?: FindOptions1;
+}
+
+export interface CreateRequest {
+  item?: Item;
+  options?: CreateOptions;
+}
+
+export interface CreateResponse {
+  created?: Item;
+}
+
+export interface IntrospectRequest {
+  item?: Item;
+}
+
+export interface IntrospectResponse {
+  item?: Item;
+  schema: string;
+  validationErrors: Error_BadRequest_FieldViolation[];
+}
+
+export interface GetRequest {
+  spaceId: string;
+  envId: string;
+  collectionId: string;
+  itemId: string;
+}
+
+export interface GetResponse {
+  item?: Item;
+}
+
+export interface FindRequest {
+  /** ID Пространства */
+  spaceId: string;
+  /** ID окружения */
+  envId: string;
+  /** ID коллекции */
+  collectionId: string;
+  filter?: Filter;
+  /** Дополнительные параметры поиска */
+  options?: FindOptions;
+}
+
+export interface FindResponse {
+  items: Item[];
+  total: number;
+}
+
+export interface UpdateRequest {
+  item?: Item;
+  options?: UpdateOptions;
+}
+
+export interface DeleteRequest {
+  spaceId: string;
+  envId: string;
+  collectionId: string;
+  itemId: string;
+  options?: DeleteOptions;
+}
+
+export interface UndeleteRequest {
+  spaceId: string;
+  envId: string;
+  collectionId: string;
+  itemId: string;
+}
+
+export interface PublishRequest {
+  item?: Item;
+  options?: PublishOptions;
+}
+
+export interface UnpublishRequest {
+  item?: Item;
+}
+
+export interface GetPublishedRequest {
+  spaceId: string;
+  envId: string;
+  collectionId: string;
+  itemId: string;
+  options?: GetPublishedOptions;
+}
+
+export interface GetPublishedResponse {
+  item?: Item;
+}
+
+export interface FindPublishedRequest {
+  spaceId: string;
+  envId: string;
+  collectionId: string;
+  filter?: Filter;
+  options?: FindPublishedOptions;
+}
+
+export interface FindPublishedResponse {
+  items: Item[];
+  total: number;
+}
+
+export interface GetRevisionRequest {
+  spaceId: string;
+  envId: string;
+  collectionId: string;
+  itemId: string;
+  revisionId: string;
+}
+
+export interface GetRevisionResponse {
+  item?: Item;
+}
+
+export interface ListRevisionsRequest {
+  spaceId: string;
+  envId: string;
+  collectionId: string;
+  itemId: string;
+  options?: ListRevisionsOptions;
+}
+
+export interface ListRevisionsResponse {
+  items: Item[];
+}
+
+/** Запрос на архивирование элемента */
+export interface ArchiveRequest {
+  /** Элемент для архивации */
+  item?: Item;
+}
+
+export interface UnarchiveRequest {
+  item?: Item;
+}
+
+export interface FindArchivedRequest {
+  spaceId: string;
+  envId: string;
+  collectionId: string;
+  filter?: Filter;
+  options?: FindArchivedOptions;
+}
+
+export interface FindArchivedResponse {
+  items: Item[];
+  total: number;
+}
+
+function createBaseError(): Error {
+  return { message: "", field: "" };
+}
+
+export const Error = {
+  encode(message: Error, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
+    if (message.message !== "") {
+      writer.uint32(10).string(message.message);
+    }
+    if (message.field !== "") {
+      writer.uint32(18).string(message.field);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Error {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseError();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.message = reader.string();
+          break;
+        case 2:
+          message.field = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Error>): Error {
+    const message = createBaseError();
+    message.message = object.message ?? "";
+    message.field = object.field ?? "";
+    return message;
+  },
+};
+
+function createBaseDecodeError(): DecodeError {
+  return { errors: [] };
+}
+
+export const DecodeError = {
+  encode(
+    message: DecodeError,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.errors) {
+      Error.encode(v!, writer.uint32(18).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): DecodeError {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseDecodeError();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 2:
+          message.errors.push(Error.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<DecodeError>): DecodeError {
+    const message = createBaseDecodeError();
+    message.errors = object.errors?.map((e) => Error.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseValidationError(): ValidationError {
+  return { errors: [] };
+}
+
+export const ValidationError = {
+  encode(
+    message: ValidationError,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.errors) {
+      Error.encode(v!, writer.uint32(18).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ValidationError {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseValidationError();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 2:
+          message.errors.push(Error.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ValidationError>): ValidationError {
+    const message = createBaseValidationError();
+    message.errors = object.errors?.map((e) => Error.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseModificationError(): ModificationError {
+  return { errors: [] };
+}
+
+export const ModificationError = {
+  encode(
+    message: ModificationError,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.errors) {
+      Error.encode(v!, writer.uint32(18).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ModificationError {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseModificationError();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 2:
+          message.errors.push(Error.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ModificationError>): ModificationError {
+    const message = createBaseModificationError();
+    message.errors = object.errors?.map((e) => Error.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBasePermissions(): Permissions {
+  return {
+    edit: false,
+    archive: false,
+    publish: false,
+    softDelete: false,
+    hardDelete: false,
+  };
+}
+
+export const Permissions = {
+  encode(
+    message: Permissions,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.edit === true) {
+      writer.uint32(8).bool(message.edit);
+    }
+    if (message.archive === true) {
+      writer.uint32(16).bool(message.archive);
+    }
+    if (message.publish === true) {
+      writer.uint32(24).bool(message.publish);
+    }
+    if (message.softDelete === true) {
+      writer.uint32(32).bool(message.softDelete);
+    }
+    if (message.hardDelete === true) {
+      writer.uint32(40).bool(message.hardDelete);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Permissions {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBasePermissions();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.edit = reader.bool();
+          break;
+        case 2:
+          message.archive = reader.bool();
+          break;
+        case 3:
+          message.publish = reader.bool();
+          break;
+        case 4:
+          message.softDelete = reader.bool();
+          break;
+        case 5:
+          message.hardDelete = reader.bool();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Permissions>): Permissions {
+    const message = createBasePermissions();
+    message.edit = object.edit ?? false;
+    message.archive = object.archive ?? false;
+    message.publish = object.publish ?? false;
+    message.softDelete = object.softDelete ?? false;
+    message.hardDelete = object.hardDelete ?? false;
+    return message;
+  },
+};
+
+function createBaseItem(): Item {
+  return {
+    id: "",
+    spaceId: "",
+    envId: "",
+    collectionId: "",
+    state: 0,
+    createdRevAt: undefined,
+    createdBy: "",
+    createdAt: undefined,
+    updatedBy: "",
+    updatedAt: undefined,
+    data: undefined,
+    translations: {},
+    revisionId: "",
+    publishedAt: undefined,
+    publishedBy: "",
+    archivedAt: undefined,
+    archivedBy: "",
+    locale: "",
+    deleted: false,
+    hidden: false,
+    template: false,
+    permissions: undefined,
+  };
+}
+
+export const Item = {
+  encode(message: Item, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
+    if (message.id !== "") {
+      writer.uint32(10).string(message.id);
+    }
+    if (message.spaceId !== "") {
+      writer.uint32(18).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(26).string(message.envId);
+    }
+    if (message.collectionId !== "") {
+      writer.uint32(34).string(message.collectionId);
+    }
+    if (message.state !== 0) {
+      writer.uint32(40).int32(message.state);
+    }
+    if (message.createdRevAt !== undefined) {
+      Timestamp.encode(message.createdRevAt, writer.uint32(50).fork()).ldelim();
+    }
+    if (message.createdBy !== "") {
+      writer.uint32(58).string(message.createdBy);
+    }
+    if (message.createdAt !== undefined) {
+      Timestamp.encode(message.createdAt, writer.uint32(66).fork()).ldelim();
+    }
+    if (message.updatedBy !== "") {
+      writer.uint32(74).string(message.updatedBy);
+    }
+    if (message.updatedAt !== undefined) {
+      Timestamp.encode(message.updatedAt, writer.uint32(82).fork()).ldelim();
+    }
+    if (message.data !== undefined) {
+      Struct.encode(
+        Struct.wrap(message.data),
+        writer.uint32(90).fork()
+      ).ldelim();
+    }
+    Object.entries(message.translations).forEach(([key, value]) => {
+      if (value !== undefined) {
+        Item_TranslationsEntry.encode(
+          { key: key as any, value },
+          writer.uint32(98).fork()
+        ).ldelim();
+      }
+    });
+    if (message.revisionId !== "") {
+      writer.uint32(106).string(message.revisionId);
+    }
+    if (message.publishedAt !== undefined) {
+      Timestamp.encode(message.publishedAt, writer.uint32(114).fork()).ldelim();
+    }
+    if (message.publishedBy !== "") {
+      writer.uint32(122).string(message.publishedBy);
+    }
+    if (message.archivedAt !== undefined) {
+      Timestamp.encode(message.archivedAt, writer.uint32(130).fork()).ldelim();
+    }
+    if (message.archivedBy !== "") {
+      writer.uint32(138).string(message.archivedBy);
+    }
+    if (message.locale !== "") {
+      writer.uint32(146).string(message.locale);
+    }
+    if (message.deleted === true) {
+      writer.uint32(152).bool(message.deleted);
+    }
+    if (message.hidden === true) {
+      writer.uint32(160).bool(message.hidden);
+    }
+    if (message.template === true) {
+      writer.uint32(168).bool(message.template);
+    }
+    if (message.permissions !== undefined) {
+      Permissions.encode(
+        message.permissions,
+        writer.uint32(178).fork()
+      ).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Item {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseItem();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.id = reader.string();
+          break;
+        case 2:
+          message.spaceId = reader.string();
+          break;
+        case 3:
+          message.envId = reader.string();
+          break;
+        case 4:
+          message.collectionId = reader.string();
+          break;
+        case 5:
+          message.state = reader.int32() as any;
+          break;
+        case 6:
+          message.createdRevAt = Timestamp.decode(reader, reader.uint32());
+          break;
+        case 7:
+          message.createdBy = reader.string();
+          break;
+        case 8:
+          message.createdAt = Timestamp.decode(reader, reader.uint32());
+          break;
+        case 9:
+          message.updatedBy = reader.string();
+          break;
+        case 10:
+          message.updatedAt = Timestamp.decode(reader, reader.uint32());
+          break;
+        case 11:
+          message.data = Struct.unwrap(Struct.decode(reader, reader.uint32()));
+          break;
+        case 12:
+          const entry12 = Item_TranslationsEntry.decode(
+            reader,
+            reader.uint32()
+          );
+          if (entry12.value !== undefined) {
+            message.translations[entry12.key] = entry12.value;
+          }
+          break;
+        case 13:
+          message.revisionId = reader.string();
+          break;
+        case 14:
+          message.publishedAt = Timestamp.decode(reader, reader.uint32());
+          break;
+        case 15:
+          message.publishedBy = reader.string();
+          break;
+        case 16:
+          message.archivedAt = Timestamp.decode(reader, reader.uint32());
+          break;
+        case 17:
+          message.archivedBy = reader.string();
+          break;
+        case 18:
+          message.locale = reader.string();
+          break;
+        case 19:
+          message.deleted = reader.bool();
+          break;
+        case 20:
+          message.hidden = reader.bool();
+          break;
+        case 21:
+          message.template = reader.bool();
+          break;
+        case 22:
+          message.permissions = Permissions.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Item>): Item {
+    const message = createBaseItem();
+    message.id = object.id ?? "";
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.collectionId = object.collectionId ?? "";
+    message.state = object.state ?? 0;
+    message.createdRevAt =
+      object.createdRevAt !== undefined && object.createdRevAt !== null
+        ? Timestamp.fromPartial(object.createdRevAt)
+        : undefined;
+    message.createdBy = object.createdBy ?? "";
+    message.createdAt =
+      object.createdAt !== undefined && object.createdAt !== null
+        ? Timestamp.fromPartial(object.createdAt)
+        : undefined;
+    message.updatedBy = object.updatedBy ?? "";
+    message.updatedAt =
+      object.updatedAt !== undefined && object.updatedAt !== null
+        ? Timestamp.fromPartial(object.updatedAt)
+        : undefined;
+    message.data = object.data ?? undefined;
+    message.translations = Object.entries(object.translations ?? {}).reduce<{
+      [key: string]: { [key: string]: any };
+    }>((acc, [key, value]) => {
+      if (value !== undefined) {
+        acc[key] = value;
+      }
+      return acc;
+    }, {});
+    message.revisionId = object.revisionId ?? "";
+    message.publishedAt =
+      object.publishedAt !== undefined && object.publishedAt !== null
+        ? Timestamp.fromPartial(object.publishedAt)
+        : undefined;
+    message.publishedBy = object.publishedBy ?? "";
+    message.archivedAt =
+      object.archivedAt !== undefined && object.archivedAt !== null
+        ? Timestamp.fromPartial(object.archivedAt)
+        : undefined;
+    message.archivedBy = object.archivedBy ?? "";
+    message.locale = object.locale ?? "";
+    message.deleted = object.deleted ?? false;
+    message.hidden = object.hidden ?? false;
+    message.template = object.template ?? false;
+    message.permissions =
+      object.permissions !== undefined && object.permissions !== null
+        ? Permissions.fromPartial(object.permissions)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseItem_TranslationsEntry(): Item_TranslationsEntry {
+  return { key: "", value: undefined };
+}
+
+export const Item_TranslationsEntry = {
+  encode(
+    message: Item_TranslationsEntry,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.key !== "") {
+      writer.uint32(10).string(message.key);
+    }
+    if (message.value !== undefined) {
+      Struct.encode(
+        Struct.wrap(message.value),
+        writer.uint32(18).fork()
+      ).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): Item_TranslationsEntry {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseItem_TranslationsEntry();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.key = reader.string();
+          break;
+        case 2:
+          message.value = Struct.unwrap(Struct.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<Item_TranslationsEntry>
+  ): Item_TranslationsEntry {
+    const message = createBaseItem_TranslationsEntry();
+    message.key = object.key ?? "";
+    message.value = object.value ?? undefined;
+    return message;
+  },
+};
+
+function createBaseFilter(): Filter {
+  return { id: [], data: [], q: [] };
+}
+
+export const Filter = {
+  encode(
+    message: Filter,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.id) {
+      writer.uint32(10).string(v!);
+    }
+    for (const v of message.data) {
+      Filter2.encode(v!, writer.uint32(18).fork()).ldelim();
+    }
+    for (const v of message.q) {
+      writer.uint32(26).string(v!);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Filter {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFilter();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.id.push(reader.string());
+          break;
+        case 2:
+          message.data.push(Filter2.decode(reader, reader.uint32()));
+          break;
+        case 3:
+          message.q.push(reader.string());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Filter>): Filter {
+    const message = createBaseFilter();
+    message.id = object.id?.map((e) => e) || [];
+    message.data = object.data?.map((e) => Filter2.fromPartial(e)) || [];
+    message.q = object.q?.map((e) => e) || [];
+    return message;
+  },
+};
+
+function createBaseCreateOptions(): CreateOptions {
+  return { updateAttrs: false };
+}
+
+export const CreateOptions = {
+  encode(
+    message: CreateOptions,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.updateAttrs === true) {
+      writer.uint32(8).bool(message.updateAttrs);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CreateOptions {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCreateOptions();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.updateAttrs = reader.bool();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CreateOptions>): CreateOptions {
+    const message = createBaseCreateOptions();
+    message.updateAttrs = object.updateAttrs ?? false;
+    return message;
+  },
+};
+
+function createBaseFindOptions(): FindOptions {
+  return {
+    options: undefined,
+    deleted: false,
+    regular: false,
+    hidden: false,
+    templates: false,
+  };
+}
+
+export const FindOptions = {
+  encode(
+    message: FindOptions,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.options !== undefined) {
+      FindOptions1.encode(message.options, writer.uint32(18).fork()).ldelim();
+    }
+    if (message.deleted === true) {
+      writer.uint32(24).bool(message.deleted);
+    }
+    if (message.regular === true) {
+      writer.uint32(32).bool(message.regular);
+    }
+    if (message.hidden === true) {
+      writer.uint32(40).bool(message.hidden);
+    }
+    if (message.templates === true) {
+      writer.uint32(48).bool(message.templates);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): FindOptions {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFindOptions();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 2:
+          message.options = FindOptions1.decode(reader, reader.uint32());
+          break;
+        case 3:
+          message.deleted = reader.bool();
+          break;
+        case 4:
+          message.regular = reader.bool();
+          break;
+        case 5:
+          message.hidden = reader.bool();
+          break;
+        case 6:
+          message.templates = reader.bool();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<FindOptions>): FindOptions {
+    const message = createBaseFindOptions();
+    message.options =
+      object.options !== undefined && object.options !== null
+        ? FindOptions1.fromPartial(object.options)
+        : undefined;
+    message.deleted = object.deleted ?? false;
+    message.regular = object.regular ?? false;
+    message.hidden = object.hidden ?? false;
+    message.templates = object.templates ?? false;
+    return message;
+  },
+};
+
+function createBaseUpdateOptions(): UpdateOptions {
+  return { updateAttrs: false };
+}
+
+export const UpdateOptions = {
+  encode(
+    message: UpdateOptions,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.updateAttrs === true) {
+      writer.uint32(8).bool(message.updateAttrs);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UpdateOptions {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUpdateOptions();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.updateAttrs = reader.bool();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UpdateOptions>): UpdateOptions {
+    const message = createBaseUpdateOptions();
+    message.updateAttrs = object.updateAttrs ?? false;
+    return message;
+  },
+};
+
+function createBaseGetPublishedOptions(): GetPublishedOptions {
+  return { localeId: "" };
+}
+
+export const GetPublishedOptions = {
+  encode(
+    message: GetPublishedOptions,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.localeId !== "") {
+      writer.uint32(10).string(message.localeId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetPublishedOptions {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetPublishedOptions();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.localeId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetPublishedOptions>): GetPublishedOptions {
+    const message = createBaseGetPublishedOptions();
+    message.localeId = object.localeId ?? "";
+    return message;
+  },
+};
+
+function createBaseDeleteOptions(): DeleteOptions {
+  return { erase: false };
+}
+
+export const DeleteOptions = {
+  encode(
+    message: DeleteOptions,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.erase === true) {
+      writer.uint32(8).bool(message.erase);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): DeleteOptions {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseDeleteOptions();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.erase = reader.bool();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<DeleteOptions>): DeleteOptions {
+    const message = createBaseDeleteOptions();
+    message.erase = object.erase ?? false;
+    return message;
+  },
+};
+
+function createBasePublishOptions(): PublishOptions {
+  return { updateAttrs: false };
+}
+
+export const PublishOptions = {
+  encode(
+    message: PublishOptions,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.updateAttrs === true) {
+      writer.uint32(8).bool(message.updateAttrs);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): PublishOptions {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBasePublishOptions();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.updateAttrs = reader.bool();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<PublishOptions>): PublishOptions {
+    const message = createBasePublishOptions();
+    message.updateAttrs = object.updateAttrs ?? false;
+    return message;
+  },
+};
+
+function createBaseFindPublishedOptions(): FindPublishedOptions {
+  return {
+    options: undefined,
+    localeId: "",
+    regular: false,
+    hidden: false,
+    templates: false,
+  };
+}
+
+export const FindPublishedOptions = {
+  encode(
+    message: FindPublishedOptions,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.options !== undefined) {
+      FindOptions1.encode(message.options, writer.uint32(18).fork()).ldelim();
+    }
+    if (message.localeId !== "") {
+      writer.uint32(26).string(message.localeId);
+    }
+    if (message.regular === true) {
+      writer.uint32(32).bool(message.regular);
+    }
+    if (message.hidden === true) {
+      writer.uint32(40).bool(message.hidden);
+    }
+    if (message.templates === true) {
+      writer.uint32(48).bool(message.templates);
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): FindPublishedOptions {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFindPublishedOptions();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 2:
+          message.options = FindOptions1.decode(reader, reader.uint32());
+          break;
+        case 3:
+          message.localeId = reader.string();
+          break;
+        case 4:
+          message.regular = reader.bool();
+          break;
+        case 5:
+          message.hidden = reader.bool();
+          break;
+        case 6:
+          message.templates = reader.bool();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<FindPublishedOptions>): FindPublishedOptions {
+    const message = createBaseFindPublishedOptions();
+    message.options =
+      object.options !== undefined && object.options !== null
+        ? FindOptions1.fromPartial(object.options)
+        : undefined;
+    message.localeId = object.localeId ?? "";
+    message.regular = object.regular ?? false;
+    message.hidden = object.hidden ?? false;
+    message.templates = object.templates ?? false;
+    return message;
+  },
+};
+
+function createBaseFindArchivedOptions(): FindArchivedOptions {
+  return { options: undefined };
+}
+
+export const FindArchivedOptions = {
+  encode(
+    message: FindArchivedOptions,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.options !== undefined) {
+      FindOptions1.encode(message.options, writer.uint32(18).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): FindArchivedOptions {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFindArchivedOptions();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 2:
+          message.options = FindOptions1.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<FindArchivedOptions>): FindArchivedOptions {
+    const message = createBaseFindArchivedOptions();
+    message.options =
+      object.options !== undefined && object.options !== null
+        ? FindOptions1.fromPartial(object.options)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseListRevisionsOptions(): ListRevisionsOptions {
+  return { options: undefined };
+}
+
+export const ListRevisionsOptions = {
+  encode(
+    message: ListRevisionsOptions,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.options !== undefined) {
+      FindOptions1.encode(message.options, writer.uint32(18).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): ListRevisionsOptions {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListRevisionsOptions();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 2:
+          message.options = FindOptions1.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListRevisionsOptions>): ListRevisionsOptions {
+    const message = createBaseListRevisionsOptions();
+    message.options =
+      object.options !== undefined && object.options !== null
+        ? FindOptions1.fromPartial(object.options)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseCreateRequest(): CreateRequest {
+  return { item: undefined, options: undefined };
+}
+
+export const CreateRequest = {
+  encode(
+    message: CreateRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.item !== undefined) {
+      Item.encode(message.item, writer.uint32(10).fork()).ldelim();
+    }
+    if (message.options !== undefined) {
+      CreateOptions.encode(message.options, writer.uint32(18).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CreateRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCreateRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.item = Item.decode(reader, reader.uint32());
+          break;
+        case 2:
+          message.options = CreateOptions.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CreateRequest>): CreateRequest {
+    const message = createBaseCreateRequest();
+    message.item =
+      object.item !== undefined && object.item !== null
+        ? Item.fromPartial(object.item)
+        : undefined;
+    message.options =
+      object.options !== undefined && object.options !== null
+        ? CreateOptions.fromPartial(object.options)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseCreateResponse(): CreateResponse {
+  return { created: undefined };
+}
+
+export const CreateResponse = {
+  encode(
+    message: CreateResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.created !== undefined) {
+      Item.encode(message.created, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CreateResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCreateResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.created = Item.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CreateResponse>): CreateResponse {
+    const message = createBaseCreateResponse();
+    message.created =
+      object.created !== undefined && object.created !== null
+        ? Item.fromPartial(object.created)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseIntrospectRequest(): IntrospectRequest {
+  return { item: undefined };
+}
+
+export const IntrospectRequest = {
+  encode(
+    message: IntrospectRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.item !== undefined) {
+      Item.encode(message.item, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): IntrospectRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseIntrospectRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.item = Item.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<IntrospectRequest>): IntrospectRequest {
+    const message = createBaseIntrospectRequest();
+    message.item =
+      object.item !== undefined && object.item !== null
+        ? Item.fromPartial(object.item)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseIntrospectResponse(): IntrospectResponse {
+  return { item: undefined, schema: "", validationErrors: [] };
+}
+
+export const IntrospectResponse = {
+  encode(
+    message: IntrospectResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.item !== undefined) {
+      Item.encode(message.item, writer.uint32(10).fork()).ldelim();
+    }
+    if (message.schema !== "") {
+      writer.uint32(18).string(message.schema);
+    }
+    for (const v of message.validationErrors) {
+      Error_BadRequest_FieldViolation.encode(
+        v!,
+        writer.uint32(26).fork()
+      ).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): IntrospectResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseIntrospectResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.item = Item.decode(reader, reader.uint32());
+          break;
+        case 2:
+          message.schema = reader.string();
+          break;
+        case 3:
+          message.validationErrors.push(
+            Error_BadRequest_FieldViolation.decode(reader, reader.uint32())
+          );
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<IntrospectResponse>): IntrospectResponse {
+    const message = createBaseIntrospectResponse();
+    message.item =
+      object.item !== undefined && object.item !== null
+        ? Item.fromPartial(object.item)
+        : undefined;
+    message.schema = object.schema ?? "";
+    message.validationErrors =
+      object.validationErrors?.map((e) =>
+        Error_BadRequest_FieldViolation.fromPartial(e)
+      ) || [];
+    return message;
+  },
+};
+
+function createBaseGetRequest(): GetRequest {
+  return { spaceId: "", envId: "", collectionId: "", itemId: "" };
+}
+
+export const GetRequest = {
+  encode(
+    message: GetRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    if (message.collectionId !== "") {
+      writer.uint32(26).string(message.collectionId);
+    }
+    if (message.itemId !== "") {
+      writer.uint32(34).string(message.itemId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        case 3:
+          message.collectionId = reader.string();
+          break;
+        case 4:
+          message.itemId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetRequest>): GetRequest {
+    const message = createBaseGetRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.collectionId = object.collectionId ?? "";
+    message.itemId = object.itemId ?? "";
+    return message;
+  },
+};
+
+function createBaseGetResponse(): GetResponse {
+  return { item: undefined };
+}
+
+export const GetResponse = {
+  encode(
+    message: GetResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.item !== undefined) {
+      Item.encode(message.item, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.item = Item.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetResponse>): GetResponse {
+    const message = createBaseGetResponse();
+    message.item =
+      object.item !== undefined && object.item !== null
+        ? Item.fromPartial(object.item)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseFindRequest(): FindRequest {
+  return {
+    spaceId: "",
+    envId: "",
+    collectionId: "",
+    filter: undefined,
+    options: undefined,
+  };
+}
+
+export const FindRequest = {
+  encode(
+    message: FindRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    if (message.collectionId !== "") {
+      writer.uint32(26).string(message.collectionId);
+    }
+    if (message.filter !== undefined) {
+      Filter.encode(message.filter, writer.uint32(34).fork()).ldelim();
+    }
+    if (message.options !== undefined) {
+      FindOptions.encode(message.options, writer.uint32(42).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): FindRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFindRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        case 3:
+          message.collectionId = reader.string();
+          break;
+        case 4:
+          message.filter = Filter.decode(reader, reader.uint32());
+          break;
+        case 5:
+          message.options = FindOptions.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<FindRequest>): FindRequest {
+    const message = createBaseFindRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.collectionId = object.collectionId ?? "";
+    message.filter =
+      object.filter !== undefined && object.filter !== null
+        ? Filter.fromPartial(object.filter)
+        : undefined;
+    message.options =
+      object.options !== undefined && object.options !== null
+        ? FindOptions.fromPartial(object.options)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseFindResponse(): FindResponse {
+  return { items: [], total: 0 };
+}
+
+export const FindResponse = {
+  encode(
+    message: FindResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.items) {
+      Item.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    if (message.total !== 0) {
+      writer.uint32(16).int32(message.total);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): FindResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFindResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.items.push(Item.decode(reader, reader.uint32()));
+          break;
+        case 2:
+          message.total = reader.int32();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<FindResponse>): FindResponse {
+    const message = createBaseFindResponse();
+    message.items = object.items?.map((e) => Item.fromPartial(e)) || [];
+    message.total = object.total ?? 0;
+    return message;
+  },
+};
+
+function createBaseUpdateRequest(): UpdateRequest {
+  return { item: undefined, options: undefined };
+}
+
+export const UpdateRequest = {
+  encode(
+    message: UpdateRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.item !== undefined) {
+      Item.encode(message.item, writer.uint32(10).fork()).ldelim();
+    }
+    if (message.options !== undefined) {
+      UpdateOptions.encode(message.options, writer.uint32(18).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UpdateRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUpdateRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.item = Item.decode(reader, reader.uint32());
+          break;
+        case 2:
+          message.options = UpdateOptions.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UpdateRequest>): UpdateRequest {
+    const message = createBaseUpdateRequest();
+    message.item =
+      object.item !== undefined && object.item !== null
+        ? Item.fromPartial(object.item)
+        : undefined;
+    message.options =
+      object.options !== undefined && object.options !== null
+        ? UpdateOptions.fromPartial(object.options)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseDeleteRequest(): DeleteRequest {
+  return {
+    spaceId: "",
+    envId: "",
+    collectionId: "",
+    itemId: "",
+    options: undefined,
+  };
+}
+
+export const DeleteRequest = {
+  encode(
+    message: DeleteRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    if (message.collectionId !== "") {
+      writer.uint32(26).string(message.collectionId);
+    }
+    if (message.itemId !== "") {
+      writer.uint32(34).string(message.itemId);
+    }
+    if (message.options !== undefined) {
+      DeleteOptions.encode(message.options, writer.uint32(42).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): DeleteRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseDeleteRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        case 3:
+          message.collectionId = reader.string();
+          break;
+        case 4:
+          message.itemId = reader.string();
+          break;
+        case 5:
+          message.options = DeleteOptions.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<DeleteRequest>): DeleteRequest {
+    const message = createBaseDeleteRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.collectionId = object.collectionId ?? "";
+    message.itemId = object.itemId ?? "";
+    message.options =
+      object.options !== undefined && object.options !== null
+        ? DeleteOptions.fromPartial(object.options)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseUndeleteRequest(): UndeleteRequest {
+  return { spaceId: "", envId: "", collectionId: "", itemId: "" };
+}
+
+export const UndeleteRequest = {
+  encode(
+    message: UndeleteRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    if (message.collectionId !== "") {
+      writer.uint32(26).string(message.collectionId);
+    }
+    if (message.itemId !== "") {
+      writer.uint32(34).string(message.itemId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UndeleteRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUndeleteRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        case 3:
+          message.collectionId = reader.string();
+          break;
+        case 4:
+          message.itemId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UndeleteRequest>): UndeleteRequest {
+    const message = createBaseUndeleteRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.collectionId = object.collectionId ?? "";
+    message.itemId = object.itemId ?? "";
+    return message;
+  },
+};
+
+function createBasePublishRequest(): PublishRequest {
+  return { item: undefined, options: undefined };
+}
+
+export const PublishRequest = {
+  encode(
+    message: PublishRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.item !== undefined) {
+      Item.encode(message.item, writer.uint32(10).fork()).ldelim();
+    }
+    if (message.options !== undefined) {
+      PublishOptions.encode(message.options, writer.uint32(18).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): PublishRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBasePublishRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.item = Item.decode(reader, reader.uint32());
+          break;
+        case 2:
+          message.options = PublishOptions.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<PublishRequest>): PublishRequest {
+    const message = createBasePublishRequest();
+    message.item =
+      object.item !== undefined && object.item !== null
+        ? Item.fromPartial(object.item)
+        : undefined;
+    message.options =
+      object.options !== undefined && object.options !== null
+        ? PublishOptions.fromPartial(object.options)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseUnpublishRequest(): UnpublishRequest {
+  return { item: undefined };
+}
+
+export const UnpublishRequest = {
+  encode(
+    message: UnpublishRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.item !== undefined) {
+      Item.encode(message.item, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UnpublishRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUnpublishRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.item = Item.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UnpublishRequest>): UnpublishRequest {
+    const message = createBaseUnpublishRequest();
+    message.item =
+      object.item !== undefined && object.item !== null
+        ? Item.fromPartial(object.item)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseGetPublishedRequest(): GetPublishedRequest {
+  return {
+    spaceId: "",
+    envId: "",
+    collectionId: "",
+    itemId: "",
+    options: undefined,
+  };
+}
+
+export const GetPublishedRequest = {
+  encode(
+    message: GetPublishedRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    if (message.collectionId !== "") {
+      writer.uint32(26).string(message.collectionId);
+    }
+    if (message.itemId !== "") {
+      writer.uint32(42).string(message.itemId);
+    }
+    if (message.options !== undefined) {
+      GetPublishedOptions.encode(
+        message.options,
+        writer.uint32(82).fork()
+      ).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetPublishedRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetPublishedRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        case 3:
+          message.collectionId = reader.string();
+          break;
+        case 5:
+          message.itemId = reader.string();
+          break;
+        case 10:
+          message.options = GetPublishedOptions.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetPublishedRequest>): GetPublishedRequest {
+    const message = createBaseGetPublishedRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.collectionId = object.collectionId ?? "";
+    message.itemId = object.itemId ?? "";
+    message.options =
+      object.options !== undefined && object.options !== null
+        ? GetPublishedOptions.fromPartial(object.options)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseGetPublishedResponse(): GetPublishedResponse {
+  return { item: undefined };
+}
+
+export const GetPublishedResponse = {
+  encode(
+    message: GetPublishedResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.item !== undefined) {
+      Item.encode(message.item, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): GetPublishedResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetPublishedResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.item = Item.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetPublishedResponse>): GetPublishedResponse {
+    const message = createBaseGetPublishedResponse();
+    message.item =
+      object.item !== undefined && object.item !== null
+        ? Item.fromPartial(object.item)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseFindPublishedRequest(): FindPublishedRequest {
+  return {
+    spaceId: "",
+    envId: "",
+    collectionId: "",
+    filter: undefined,
+    options: undefined,
+  };
+}
+
+export const FindPublishedRequest = {
+  encode(
+    message: FindPublishedRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    if (message.collectionId !== "") {
+      writer.uint32(26).string(message.collectionId);
+    }
+    if (message.filter !== undefined) {
+      Filter.encode(message.filter, writer.uint32(34).fork()).ldelim();
+    }
+    if (message.options !== undefined) {
+      FindPublishedOptions.encode(
+        message.options,
+        writer.uint32(82).fork()
+      ).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): FindPublishedRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFindPublishedRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        case 3:
+          message.collectionId = reader.string();
+          break;
+        case 4:
+          message.filter = Filter.decode(reader, reader.uint32());
+          break;
+        case 10:
+          message.options = FindPublishedOptions.decode(
+            reader,
+            reader.uint32()
+          );
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<FindPublishedRequest>): FindPublishedRequest {
+    const message = createBaseFindPublishedRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.collectionId = object.collectionId ?? "";
+    message.filter =
+      object.filter !== undefined && object.filter !== null
+        ? Filter.fromPartial(object.filter)
+        : undefined;
+    message.options =
+      object.options !== undefined && object.options !== null
+        ? FindPublishedOptions.fromPartial(object.options)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseFindPublishedResponse(): FindPublishedResponse {
+  return { items: [], total: 0 };
+}
+
+export const FindPublishedResponse = {
+  encode(
+    message: FindPublishedResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.items) {
+      Item.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    if (message.total !== 0) {
+      writer.uint32(16).int32(message.total);
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): FindPublishedResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFindPublishedResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.items.push(Item.decode(reader, reader.uint32()));
+          break;
+        case 2:
+          message.total = reader.int32();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<FindPublishedResponse>
+  ): FindPublishedResponse {
+    const message = createBaseFindPublishedResponse();
+    message.items = object.items?.map((e) => Item.fromPartial(e)) || [];
+    message.total = object.total ?? 0;
+    return message;
+  },
+};
+
+function createBaseGetRevisionRequest(): GetRevisionRequest {
+  return {
+    spaceId: "",
+    envId: "",
+    collectionId: "",
+    itemId: "",
+    revisionId: "",
+  };
+}
+
+export const GetRevisionRequest = {
+  encode(
+    message: GetRevisionRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    if (message.collectionId !== "") {
+      writer.uint32(26).string(message.collectionId);
+    }
+    if (message.itemId !== "") {
+      writer.uint32(34).string(message.itemId);
+    }
+    if (message.revisionId !== "") {
+      writer.uint32(42).string(message.revisionId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetRevisionRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetRevisionRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        case 3:
+          message.collectionId = reader.string();
+          break;
+        case 4:
+          message.itemId = reader.string();
+          break;
+        case 5:
+          message.revisionId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetRevisionRequest>): GetRevisionRequest {
+    const message = createBaseGetRevisionRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.collectionId = object.collectionId ?? "";
+    message.itemId = object.itemId ?? "";
+    message.revisionId = object.revisionId ?? "";
+    return message;
+  },
+};
+
+function createBaseGetRevisionResponse(): GetRevisionResponse {
+  return { item: undefined };
+}
+
+export const GetRevisionResponse = {
+  encode(
+    message: GetRevisionResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.item !== undefined) {
+      Item.encode(message.item, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetRevisionResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetRevisionResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.item = Item.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetRevisionResponse>): GetRevisionResponse {
+    const message = createBaseGetRevisionResponse();
+    message.item =
+      object.item !== undefined && object.item !== null
+        ? Item.fromPartial(object.item)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseListRevisionsRequest(): ListRevisionsRequest {
+  return {
+    spaceId: "",
+    envId: "",
+    collectionId: "",
+    itemId: "",
+    options: undefined,
+  };
+}
+
+export const ListRevisionsRequest = {
+  encode(
+    message: ListRevisionsRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    if (message.collectionId !== "") {
+      writer.uint32(26).string(message.collectionId);
+    }
+    if (message.itemId !== "") {
+      writer.uint32(34).string(message.itemId);
+    }
+    if (message.options !== undefined) {
+      ListRevisionsOptions.encode(
+        message.options,
+        writer.uint32(82).fork()
+      ).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): ListRevisionsRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListRevisionsRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        case 3:
+          message.collectionId = reader.string();
+          break;
+        case 4:
+          message.itemId = reader.string();
+          break;
+        case 10:
+          message.options = ListRevisionsOptions.decode(
+            reader,
+            reader.uint32()
+          );
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListRevisionsRequest>): ListRevisionsRequest {
+    const message = createBaseListRevisionsRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.collectionId = object.collectionId ?? "";
+    message.itemId = object.itemId ?? "";
+    message.options =
+      object.options !== undefined && object.options !== null
+        ? ListRevisionsOptions.fromPartial(object.options)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseListRevisionsResponse(): ListRevisionsResponse {
+  return { items: [] };
+}
+
+export const ListRevisionsResponse = {
+  encode(
+    message: ListRevisionsResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.items) {
+      Item.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): ListRevisionsResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListRevisionsResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.items.push(Item.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<ListRevisionsResponse>
+  ): ListRevisionsResponse {
+    const message = createBaseListRevisionsResponse();
+    message.items = object.items?.map((e) => Item.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseArchiveRequest(): ArchiveRequest {
+  return { item: undefined };
+}
+
+export const ArchiveRequest = {
+  encode(
+    message: ArchiveRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.item !== undefined) {
+      Item.encode(message.item, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ArchiveRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseArchiveRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.item = Item.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ArchiveRequest>): ArchiveRequest {
+    const message = createBaseArchiveRequest();
+    message.item =
+      object.item !== undefined && object.item !== null
+        ? Item.fromPartial(object.item)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseUnarchiveRequest(): UnarchiveRequest {
+  return { item: undefined };
+}
+
+export const UnarchiveRequest = {
+  encode(
+    message: UnarchiveRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.item !== undefined) {
+      Item.encode(message.item, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UnarchiveRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUnarchiveRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.item = Item.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UnarchiveRequest>): UnarchiveRequest {
+    const message = createBaseUnarchiveRequest();
+    message.item =
+      object.item !== undefined && object.item !== null
+        ? Item.fromPartial(object.item)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseFindArchivedRequest(): FindArchivedRequest {
+  return {
+    spaceId: "",
+    envId: "",
+    collectionId: "",
+    filter: undefined,
+    options: undefined,
+  };
+}
+
+export const FindArchivedRequest = {
+  encode(
+    message: FindArchivedRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    if (message.collectionId !== "") {
+      writer.uint32(26).string(message.collectionId);
+    }
+    if (message.filter !== undefined) {
+      Filter.encode(message.filter, writer.uint32(34).fork()).ldelim();
+    }
+    if (message.options !== undefined) {
+      FindArchivedOptions.encode(
+        message.options,
+        writer.uint32(50).fork()
+      ).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): FindArchivedRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFindArchivedRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        case 3:
+          message.collectionId = reader.string();
+          break;
+        case 4:
+          message.filter = Filter.decode(reader, reader.uint32());
+          break;
+        case 6:
+          message.options = FindArchivedOptions.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<FindArchivedRequest>): FindArchivedRequest {
+    const message = createBaseFindArchivedRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.collectionId = object.collectionId ?? "";
+    message.filter =
+      object.filter !== undefined && object.filter !== null
+        ? Filter.fromPartial(object.filter)
+        : undefined;
+    message.options =
+      object.options !== undefined && object.options !== null
+        ? FindArchivedOptions.fromPartial(object.options)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseFindArchivedResponse(): FindArchivedResponse {
+  return { items: [], total: 0 };
+}
+
+export const FindArchivedResponse = {
+  encode(
+    message: FindArchivedResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.items) {
+      Item.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    if (message.total !== 0) {
+      writer.uint32(16).int32(message.total);
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): FindArchivedResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFindArchivedResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.items.push(Item.decode(reader, reader.uint32()));
+          break;
+        case 2:
+          message.total = reader.int32();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<FindArchivedResponse>): FindArchivedResponse {
+    const message = createBaseFindArchivedResponse();
+    message.items = object.items?.map((e) => Item.fromPartial(e)) || [];
+    message.total = object.total ?? 0;
+    return message;
+  },
+};
+
+/** Сервис API элементов */
+export type ItemsDefinition = typeof ItemsDefinition;
+export const ItemsDefinition = {
+  name: "Items",
+  fullName: "content.items.Items",
+  methods: {
+    /** Создать запись */
+    create: {
+      name: "Create",
+      requestType: CreateRequest,
+      requestStream: false,
+      responseType: CreateResponse,
+      responseStream: false,
+      options: {},
+    },
+    /** Валидация данных записи */
+    introspect: {
+      name: "Introspect",
+      requestType: IntrospectRequest,
+      requestStream: false,
+      responseType: IntrospectResponse,
+      responseStream: false,
+      options: {},
+    },
+    /** Получение записи по идентификатору */
+    get: {
+      name: "Get",
+      requestType: GetRequest,
+      requestStream: false,
+      responseType: GetResponse,
+      responseStream: false,
+      options: {},
+    },
+    /** Поиск по текущим записям */
+    find: {
+      name: "Find",
+      requestType: FindRequest,
+      requestStream: false,
+      responseType: FindResponse,
+      responseStream: false,
+      options: {},
+    },
+    update: {
+      name: "Update",
+      requestType: UpdateRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    delete: {
+      name: "Delete",
+      requestType: DeleteRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    undelete: {
+      name: "Undelete",
+      requestType: UndeleteRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    publish: {
+      name: "Publish",
+      requestType: PublishRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    unpublish: {
+      name: "Unpublish",
+      requestType: UnpublishRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    getPublished: {
+      name: "GetPublished",
+      requestType: GetPublishedRequest,
+      requestStream: false,
+      responseType: GetPublishedResponse,
+      responseStream: false,
+      options: {},
+    },
+    findPublished: {
+      name: "FindPublished",
+      requestType: FindPublishedRequest,
+      requestStream: false,
+      responseType: FindPublishedResponse,
+      responseStream: false,
+      options: {},
+    },
+    getRevision: {
+      name: "GetRevision",
+      requestType: GetRevisionRequest,
+      requestStream: false,
+      responseType: GetRevisionResponse,
+      responseStream: false,
+      options: {},
+    },
+    listRevisions: {
+      name: "ListRevisions",
+      requestType: ListRevisionsRequest,
+      requestStream: false,
+      responseType: ListRevisionsResponse,
+      responseStream: false,
+      options: {},
+    },
+    archive: {
+      name: "Archive",
+      requestType: ArchiveRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    findArchived: {
+      name: "FindArchived",
+      requestType: FindArchivedRequest,
+      requestStream: false,
+      responseType: FindArchivedResponse,
+      responseStream: false,
+      options: {},
+    },
+    unarchive: {
+      name: "Unarchive",
+      requestType: UnarchiveRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+  },
+} as const;
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
diff --git a/clients/locales/index.d.ts b/clients/locales/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..631c2cd077995af0e04d0483275eb079471f2d93
--- /dev/null
+++ b/clients/locales/index.d.ts
@@ -0,0 +1,2 @@
+export * from './locales';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/locales/index.d.ts.map b/clients/locales/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..14874de52675a779161f9283e8c8ca83f8bf4ff0
--- /dev/null
+++ b/clients/locales/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA"}
\ No newline at end of file
diff --git a/clients/locales/index.js b/clients/locales/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..9e2e523d4f97d90a4506f2689b8c18be8ab94e23
--- /dev/null
+++ b/clients/locales/index.js
@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./locales"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/locales/index.js.map b/clients/locales/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..c4db403c06de7ffa79f19965575626b77eace5a4
--- /dev/null
+++ b/clients/locales/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAAyB"}
\ No newline at end of file
diff --git a/clients/locales/locales.ts b/clients/locales/locales.ts
new file mode 100644
index 0000000000000000000000000000000000000000..64adbd89122d4815d2aa0a7c039b3314b68364d4
--- /dev/null
+++ b/clients/locales/locales.ts
@@ -0,0 +1,348 @@
+/* eslint-disable */
+import { Empty } from "../google/protobuf/empty";
+import * as _m0 from "protobufjs/minimal";
+
+export interface Locale {
+  id: string;
+  spaceId: string;
+  name: string;
+}
+
+export interface CreateRequest {
+  locale?: Locale;
+}
+
+export interface CreateResponse {
+  locale?: Locale;
+}
+
+export interface ListRequest {
+  spaceId: string;
+}
+
+export interface ListResponse {
+  locales: Locale[];
+}
+
+export interface DeleteRequest {
+  spaceId: string;
+  localeId: string;
+}
+
+function createBaseLocale(): Locale {
+  return { id: "", spaceId: "", name: "" };
+}
+
+export const Locale = {
+  encode(
+    message: Locale,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.id !== "") {
+      writer.uint32(10).string(message.id);
+    }
+    if (message.spaceId !== "") {
+      writer.uint32(18).string(message.spaceId);
+    }
+    if (message.name !== "") {
+      writer.uint32(26).string(message.name);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Locale {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseLocale();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.id = reader.string();
+          break;
+        case 2:
+          message.spaceId = reader.string();
+          break;
+        case 3:
+          message.name = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Locale>): Locale {
+    const message = createBaseLocale();
+    message.id = object.id ?? "";
+    message.spaceId = object.spaceId ?? "";
+    message.name = object.name ?? "";
+    return message;
+  },
+};
+
+function createBaseCreateRequest(): CreateRequest {
+  return { locale: undefined };
+}
+
+export const CreateRequest = {
+  encode(
+    message: CreateRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.locale !== undefined) {
+      Locale.encode(message.locale, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CreateRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCreateRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.locale = Locale.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CreateRequest>): CreateRequest {
+    const message = createBaseCreateRequest();
+    message.locale =
+      object.locale !== undefined && object.locale !== null
+        ? Locale.fromPartial(object.locale)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseCreateResponse(): CreateResponse {
+  return { locale: undefined };
+}
+
+export const CreateResponse = {
+  encode(
+    message: CreateResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.locale !== undefined) {
+      Locale.encode(message.locale, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CreateResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCreateResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.locale = Locale.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CreateResponse>): CreateResponse {
+    const message = createBaseCreateResponse();
+    message.locale =
+      object.locale !== undefined && object.locale !== null
+        ? Locale.fromPartial(object.locale)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseListRequest(): ListRequest {
+  return { spaceId: "" };
+}
+
+export const ListRequest = {
+  encode(
+    message: ListRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ListRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListRequest>): ListRequest {
+    const message = createBaseListRequest();
+    message.spaceId = object.spaceId ?? "";
+    return message;
+  },
+};
+
+function createBaseListResponse(): ListResponse {
+  return { locales: [] };
+}
+
+export const ListResponse = {
+  encode(
+    message: ListResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.locales) {
+      Locale.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ListResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.locales.push(Locale.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListResponse>): ListResponse {
+    const message = createBaseListResponse();
+    message.locales = object.locales?.map((e) => Locale.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseDeleteRequest(): DeleteRequest {
+  return { spaceId: "", localeId: "" };
+}
+
+export const DeleteRequest = {
+  encode(
+    message: DeleteRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.localeId !== "") {
+      writer.uint32(18).string(message.localeId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): DeleteRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseDeleteRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.localeId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<DeleteRequest>): DeleteRequest {
+    const message = createBaseDeleteRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.localeId = object.localeId ?? "";
+    return message;
+  },
+};
+
+export type LocalesDefinition = typeof LocalesDefinition;
+export const LocalesDefinition = {
+  name: "Locales",
+  fullName: "content.locales.Locales",
+  methods: {
+    create: {
+      name: "Create",
+      requestType: CreateRequest,
+      requestStream: false,
+      responseType: CreateResponse,
+      responseStream: false,
+      options: {},
+    },
+    list: {
+      name: "List",
+      requestType: ListRequest,
+      requestStream: false,
+      responseType: ListResponse,
+      responseStream: false,
+      options: {},
+    },
+    delete: {
+      name: "Delete",
+      requestType: DeleteRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+  },
+} as const;
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
diff --git a/clients/members/index.d.ts b/clients/members/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e1e1e6c0ef3eccce62229ba9eba4a16eff9e77e1
--- /dev/null
+++ b/clients/members/index.d.ts
@@ -0,0 +1,2 @@
+export * from './members';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/members/index.d.ts.map b/clients/members/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..14874de52675a779161f9283e8c8ca83f8bf4ff0
--- /dev/null
+++ b/clients/members/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA"}
\ No newline at end of file
diff --git a/clients/members/index.js b/clients/members/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..f542d1a0b020804ad2bab05c6bc3db17d6cf6ba2
--- /dev/null
+++ b/clients/members/index.js
@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./members"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/members/index.js.map b/clients/members/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..c4db403c06de7ffa79f19965575626b77eace5a4
--- /dev/null
+++ b/clients/members/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAAyB"}
\ No newline at end of file
diff --git a/clients/members/members.ts b/clients/members/members.ts
new file mode 100644
index 0000000000000000000000000000000000000000..66ae8f7517f12faa56df0e7142b171211f16d10e
--- /dev/null
+++ b/clients/members/members.ts
@@ -0,0 +1,663 @@
+/* eslint-disable */
+import { Collaborator } from "../common/common";
+import { Empty } from "../google/protobuf/empty";
+import * as _m0 from "protobufjs/minimal";
+
+/** Роль пользователя в организации */
+export enum Role {
+  /** NOT_MEMBER - Не является членом команды - значение по умолчанию */
+  NOT_MEMBER = 0,
+  /** MEMBER - Входит в организацию и команды, может получать доступ к Space в соответствии с политикой доступа */
+  MEMBER = 1,
+  /** OWNER - admin + может приглашать пользователей на роль owner */
+  OWNER = 2,
+  /** ADMIN - Входит в организацию, видит все Space, может задавать политики доступа, может приглашать пользователей на роли member, admin */
+  ADMIN = 3,
+  UNRECOGNIZED = -1,
+}
+
+export interface Member {
+  orgId: string;
+  userId: string;
+  role: Role;
+}
+
+export interface SetRequest {
+  orgId: string;
+  userId: string;
+  role: Role;
+}
+
+export interface GetRequest {
+  orgId: string;
+  userId: string;
+}
+
+export interface GetResponse {
+  role: Role;
+}
+
+export interface RemoveRequest {
+  orgId: string;
+  userId: string;
+}
+
+export interface ListMembersRequest {
+  orgId: string;
+}
+
+export interface ListMembersResponse {
+  members: Member[];
+}
+
+export interface ListOrganizationsRequest {
+  userId: string;
+}
+
+export interface ListOrganizationsResponse {
+  organizations: Member[];
+}
+
+/**
+ * Внутренний сервис (часть имплементации паттерна Observer). Используется для установки
+ * членства в организации при принятии приглашения в пространство
+ */
+export interface OnCollaboratorSetRequest {
+  collaborator?: Collaborator;
+}
+
+export interface OnCollaboratorSetResponse {
+  delayedTaskId: string;
+}
+
+function createBaseMember(): Member {
+  return { orgId: "", userId: "", role: 0 };
+}
+
+export const Member = {
+  encode(
+    message: Member,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.orgId !== "") {
+      writer.uint32(10).string(message.orgId);
+    }
+    if (message.userId !== "") {
+      writer.uint32(18).string(message.userId);
+    }
+    if (message.role !== 0) {
+      writer.uint32(24).int32(message.role);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Member {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseMember();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.orgId = reader.string();
+          break;
+        case 2:
+          message.userId = reader.string();
+          break;
+        case 3:
+          message.role = reader.int32() as any;
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Member>): Member {
+    const message = createBaseMember();
+    message.orgId = object.orgId ?? "";
+    message.userId = object.userId ?? "";
+    message.role = object.role ?? 0;
+    return message;
+  },
+};
+
+function createBaseSetRequest(): SetRequest {
+  return { orgId: "", userId: "", role: 0 };
+}
+
+export const SetRequest = {
+  encode(
+    message: SetRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.orgId !== "") {
+      writer.uint32(10).string(message.orgId);
+    }
+    if (message.userId !== "") {
+      writer.uint32(18).string(message.userId);
+    }
+    if (message.role !== 0) {
+      writer.uint32(24).int32(message.role);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): SetRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseSetRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.orgId = reader.string();
+          break;
+        case 2:
+          message.userId = reader.string();
+          break;
+        case 3:
+          message.role = reader.int32() as any;
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<SetRequest>): SetRequest {
+    const message = createBaseSetRequest();
+    message.orgId = object.orgId ?? "";
+    message.userId = object.userId ?? "";
+    message.role = object.role ?? 0;
+    return message;
+  },
+};
+
+function createBaseGetRequest(): GetRequest {
+  return { orgId: "", userId: "" };
+}
+
+export const GetRequest = {
+  encode(
+    message: GetRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.orgId !== "") {
+      writer.uint32(10).string(message.orgId);
+    }
+    if (message.userId !== "") {
+      writer.uint32(18).string(message.userId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.orgId = reader.string();
+          break;
+        case 2:
+          message.userId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetRequest>): GetRequest {
+    const message = createBaseGetRequest();
+    message.orgId = object.orgId ?? "";
+    message.userId = object.userId ?? "";
+    return message;
+  },
+};
+
+function createBaseGetResponse(): GetResponse {
+  return { role: 0 };
+}
+
+export const GetResponse = {
+  encode(
+    message: GetResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.role !== 0) {
+      writer.uint32(24).int32(message.role);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 3:
+          message.role = reader.int32() as any;
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetResponse>): GetResponse {
+    const message = createBaseGetResponse();
+    message.role = object.role ?? 0;
+    return message;
+  },
+};
+
+function createBaseRemoveRequest(): RemoveRequest {
+  return { orgId: "", userId: "" };
+}
+
+export const RemoveRequest = {
+  encode(
+    message: RemoveRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.orgId !== "") {
+      writer.uint32(10).string(message.orgId);
+    }
+    if (message.userId !== "") {
+      writer.uint32(18).string(message.userId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): RemoveRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseRemoveRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.orgId = reader.string();
+          break;
+        case 2:
+          message.userId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<RemoveRequest>): RemoveRequest {
+    const message = createBaseRemoveRequest();
+    message.orgId = object.orgId ?? "";
+    message.userId = object.userId ?? "";
+    return message;
+  },
+};
+
+function createBaseListMembersRequest(): ListMembersRequest {
+  return { orgId: "" };
+}
+
+export const ListMembersRequest = {
+  encode(
+    message: ListMembersRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.orgId !== "") {
+      writer.uint32(10).string(message.orgId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ListMembersRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListMembersRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.orgId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListMembersRequest>): ListMembersRequest {
+    const message = createBaseListMembersRequest();
+    message.orgId = object.orgId ?? "";
+    return message;
+  },
+};
+
+function createBaseListMembersResponse(): ListMembersResponse {
+  return { members: [] };
+}
+
+export const ListMembersResponse = {
+  encode(
+    message: ListMembersResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.members) {
+      Member.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ListMembersResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListMembersResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.members.push(Member.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListMembersResponse>): ListMembersResponse {
+    const message = createBaseListMembersResponse();
+    message.members = object.members?.map((e) => Member.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseListOrganizationsRequest(): ListOrganizationsRequest {
+  return { userId: "" };
+}
+
+export const ListOrganizationsRequest = {
+  encode(
+    message: ListOrganizationsRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.userId !== "") {
+      writer.uint32(10).string(message.userId);
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): ListOrganizationsRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListOrganizationsRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.userId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<ListOrganizationsRequest>
+  ): ListOrganizationsRequest {
+    const message = createBaseListOrganizationsRequest();
+    message.userId = object.userId ?? "";
+    return message;
+  },
+};
+
+function createBaseListOrganizationsResponse(): ListOrganizationsResponse {
+  return { organizations: [] };
+}
+
+export const ListOrganizationsResponse = {
+  encode(
+    message: ListOrganizationsResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.organizations) {
+      Member.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): ListOrganizationsResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListOrganizationsResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.organizations.push(Member.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<ListOrganizationsResponse>
+  ): ListOrganizationsResponse {
+    const message = createBaseListOrganizationsResponse();
+    message.organizations =
+      object.organizations?.map((e) => Member.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseOnCollaboratorSetRequest(): OnCollaboratorSetRequest {
+  return { collaborator: undefined };
+}
+
+export const OnCollaboratorSetRequest = {
+  encode(
+    message: OnCollaboratorSetRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.collaborator !== undefined) {
+      Collaborator.encode(
+        message.collaborator,
+        writer.uint32(10).fork()
+      ).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): OnCollaboratorSetRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseOnCollaboratorSetRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.collaborator = Collaborator.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<OnCollaboratorSetRequest>
+  ): OnCollaboratorSetRequest {
+    const message = createBaseOnCollaboratorSetRequest();
+    message.collaborator =
+      object.collaborator !== undefined && object.collaborator !== null
+        ? Collaborator.fromPartial(object.collaborator)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseOnCollaboratorSetResponse(): OnCollaboratorSetResponse {
+  return { delayedTaskId: "" };
+}
+
+export const OnCollaboratorSetResponse = {
+  encode(
+    message: OnCollaboratorSetResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.delayedTaskId !== "") {
+      writer.uint32(10).string(message.delayedTaskId);
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): OnCollaboratorSetResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseOnCollaboratorSetResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.delayedTaskId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<OnCollaboratorSetResponse>
+  ): OnCollaboratorSetResponse {
+    const message = createBaseOnCollaboratorSetResponse();
+    message.delayedTaskId = object.delayedTaskId ?? "";
+    return message;
+  },
+};
+
+export type MembersDefinition = typeof MembersDefinition;
+export const MembersDefinition = {
+  name: "Members",
+  fullName: "account.members.Members",
+  methods: {
+    set: {
+      name: "Set",
+      requestType: SetRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    get: {
+      name: "Get",
+      requestType: GetRequest,
+      requestStream: false,
+      responseType: GetResponse,
+      responseStream: false,
+      options: {},
+    },
+    remove: {
+      name: "Remove",
+      requestType: RemoveRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    listMembers: {
+      name: "ListMembers",
+      requestType: ListMembersRequest,
+      requestStream: false,
+      responseType: ListMembersResponse,
+      responseStream: false,
+      options: {},
+    },
+    listOrganizations: {
+      name: "ListOrganizations",
+      requestType: ListOrganizationsRequest,
+      requestStream: false,
+      responseType: ListOrganizationsResponse,
+      responseStream: false,
+      options: {},
+    },
+  },
+} as const;
+
+export type ObserverDefinition = typeof ObserverDefinition;
+export const ObserverDefinition = {
+  name: "Observer",
+  fullName: "account.members.Observer",
+  methods: {
+    onCollaboratorSet: {
+      name: "OnCollaboratorSet",
+      requestType: OnCollaboratorSetRequest,
+      requestStream: false,
+      responseType: OnCollaboratorSetResponse,
+      responseStream: false,
+      options: {},
+    },
+  },
+} as const;
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
diff --git a/clients/organizations/index.d.ts b/clients/organizations/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..552929425b01209a0c3a2cab5bbf03f817b14ee8
--- /dev/null
+++ b/clients/organizations/index.d.ts
@@ -0,0 +1,2 @@
+export * from './organizations';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/organizations/index.d.ts.map b/clients/organizations/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..af6256bd84692b57f2bad605bed20be9c33e01e8
--- /dev/null
+++ b/clients/organizations/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA"}
\ No newline at end of file
diff --git a/clients/organizations/index.js b/clients/organizations/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..56ae7cb9e0ddef1616fc82f5b7262a728a9f16c8
--- /dev/null
+++ b/clients/organizations/index.js
@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./organizations"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/organizations/index.js.map b/clients/organizations/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..77c64a5e9dd05cb19d3c871162cb64cea8a2371b
--- /dev/null
+++ b/clients/organizations/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAA+B"}
\ No newline at end of file
diff --git a/clients/organizations/organizations.ts b/clients/organizations/organizations.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5ff9d88cdb0dc9d9c5a7faff19f17d6151a43093
--- /dev/null
+++ b/clients/organizations/organizations.ts
@@ -0,0 +1,614 @@
+/* eslint-disable */
+import { FindOptions } from "../common/common";
+import Long from "long";
+import { Empty } from "../google/protobuf/empty";
+import * as _m0 from "protobufjs/minimal";
+
+/** Организация */
+export interface Organization {
+  /** Идентификатор организации */
+  id: string;
+  /** Имя организации */
+  name: string;
+  /** Описание организации */
+  description: string;
+  /** URI изображения логотипа */
+  logoUrl: string;
+  ownerId?: string | undefined;
+}
+
+export interface CreateRequest {
+  org?: Organization;
+}
+
+export interface CreateResponse {
+  created?: Organization;
+}
+
+export interface GetRequest {
+  orgId: string;
+}
+
+export interface GetResponse {
+  org?: Organization;
+}
+
+export interface UpdateRequest {
+  org?: Organization;
+}
+
+export interface DeleteRequest {
+  orgId: string;
+}
+
+export interface Filter {
+  ids: string[];
+  names: string[];
+}
+
+export interface FindRequest {
+  filter?: Filter;
+  opts?: FindOptions;
+}
+
+export interface FindResponse {
+  orgs: Organization[];
+  total: number;
+}
+
+function createBaseOrganization(): Organization {
+  return { id: "", name: "", description: "", logoUrl: "", ownerId: undefined };
+}
+
+export const Organization = {
+  encode(
+    message: Organization,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.id !== "") {
+      writer.uint32(10).string(message.id);
+    }
+    if (message.name !== "") {
+      writer.uint32(18).string(message.name);
+    }
+    if (message.description !== "") {
+      writer.uint32(26).string(message.description);
+    }
+    if (message.logoUrl !== "") {
+      writer.uint32(42).string(message.logoUrl);
+    }
+    if (message.ownerId !== undefined) {
+      writer.uint32(50).string(message.ownerId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Organization {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseOrganization();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.id = reader.string();
+          break;
+        case 2:
+          message.name = reader.string();
+          break;
+        case 3:
+          message.description = reader.string();
+          break;
+        case 5:
+          message.logoUrl = reader.string();
+          break;
+        case 6:
+          message.ownerId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Organization>): Organization {
+    const message = createBaseOrganization();
+    message.id = object.id ?? "";
+    message.name = object.name ?? "";
+    message.description = object.description ?? "";
+    message.logoUrl = object.logoUrl ?? "";
+    message.ownerId = object.ownerId ?? undefined;
+    return message;
+  },
+};
+
+function createBaseCreateRequest(): CreateRequest {
+  return { org: undefined };
+}
+
+export const CreateRequest = {
+  encode(
+    message: CreateRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.org !== undefined) {
+      Organization.encode(message.org, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CreateRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCreateRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.org = Organization.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CreateRequest>): CreateRequest {
+    const message = createBaseCreateRequest();
+    message.org =
+      object.org !== undefined && object.org !== null
+        ? Organization.fromPartial(object.org)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseCreateResponse(): CreateResponse {
+  return { created: undefined };
+}
+
+export const CreateResponse = {
+  encode(
+    message: CreateResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.created !== undefined) {
+      Organization.encode(message.created, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CreateResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCreateResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.created = Organization.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CreateResponse>): CreateResponse {
+    const message = createBaseCreateResponse();
+    message.created =
+      object.created !== undefined && object.created !== null
+        ? Organization.fromPartial(object.created)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseGetRequest(): GetRequest {
+  return { orgId: "" };
+}
+
+export const GetRequest = {
+  encode(
+    message: GetRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.orgId !== "") {
+      writer.uint32(10).string(message.orgId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.orgId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetRequest>): GetRequest {
+    const message = createBaseGetRequest();
+    message.orgId = object.orgId ?? "";
+    return message;
+  },
+};
+
+function createBaseGetResponse(): GetResponse {
+  return { org: undefined };
+}
+
+export const GetResponse = {
+  encode(
+    message: GetResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.org !== undefined) {
+      Organization.encode(message.org, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.org = Organization.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetResponse>): GetResponse {
+    const message = createBaseGetResponse();
+    message.org =
+      object.org !== undefined && object.org !== null
+        ? Organization.fromPartial(object.org)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseUpdateRequest(): UpdateRequest {
+  return { org: undefined };
+}
+
+export const UpdateRequest = {
+  encode(
+    message: UpdateRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.org !== undefined) {
+      Organization.encode(message.org, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UpdateRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUpdateRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.org = Organization.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UpdateRequest>): UpdateRequest {
+    const message = createBaseUpdateRequest();
+    message.org =
+      object.org !== undefined && object.org !== null
+        ? Organization.fromPartial(object.org)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseDeleteRequest(): DeleteRequest {
+  return { orgId: "" };
+}
+
+export const DeleteRequest = {
+  encode(
+    message: DeleteRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.orgId !== "") {
+      writer.uint32(10).string(message.orgId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): DeleteRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseDeleteRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.orgId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<DeleteRequest>): DeleteRequest {
+    const message = createBaseDeleteRequest();
+    message.orgId = object.orgId ?? "";
+    return message;
+  },
+};
+
+function createBaseFilter(): Filter {
+  return { ids: [], names: [] };
+}
+
+export const Filter = {
+  encode(
+    message: Filter,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.ids) {
+      writer.uint32(26).string(v!);
+    }
+    for (const v of message.names) {
+      writer.uint32(34).string(v!);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Filter {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFilter();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 3:
+          message.ids.push(reader.string());
+          break;
+        case 4:
+          message.names.push(reader.string());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Filter>): Filter {
+    const message = createBaseFilter();
+    message.ids = object.ids?.map((e) => e) || [];
+    message.names = object.names?.map((e) => e) || [];
+    return message;
+  },
+};
+
+function createBaseFindRequest(): FindRequest {
+  return { filter: undefined, opts: undefined };
+}
+
+export const FindRequest = {
+  encode(
+    message: FindRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.filter !== undefined) {
+      Filter.encode(message.filter, writer.uint32(10).fork()).ldelim();
+    }
+    if (message.opts !== undefined) {
+      FindOptions.encode(message.opts, writer.uint32(18).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): FindRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFindRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.filter = Filter.decode(reader, reader.uint32());
+          break;
+        case 2:
+          message.opts = FindOptions.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<FindRequest>): FindRequest {
+    const message = createBaseFindRequest();
+    message.filter =
+      object.filter !== undefined && object.filter !== null
+        ? Filter.fromPartial(object.filter)
+        : undefined;
+    message.opts =
+      object.opts !== undefined && object.opts !== null
+        ? FindOptions.fromPartial(object.opts)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseFindResponse(): FindResponse {
+  return { orgs: [], total: 0 };
+}
+
+export const FindResponse = {
+  encode(
+    message: FindResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.orgs) {
+      Organization.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    if (message.total !== 0) {
+      writer.uint32(16).int64(message.total);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): FindResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFindResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.orgs.push(Organization.decode(reader, reader.uint32()));
+          break;
+        case 2:
+          message.total = longToNumber(reader.int64() as Long);
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<FindResponse>): FindResponse {
+    const message = createBaseFindResponse();
+    message.orgs = object.orgs?.map((e) => Organization.fromPartial(e)) || [];
+    message.total = object.total ?? 0;
+    return message;
+  },
+};
+
+export type OrganizationsDefinition = typeof OrganizationsDefinition;
+export const OrganizationsDefinition = {
+  name: "Organizations",
+  fullName: "account.organizations.Organizations",
+  methods: {
+    create: {
+      name: "Create",
+      requestType: CreateRequest,
+      requestStream: false,
+      responseType: CreateResponse,
+      responseStream: false,
+      options: {},
+    },
+    get: {
+      name: "Get",
+      requestType: GetRequest,
+      requestStream: false,
+      responseType: GetResponse,
+      responseStream: false,
+      options: {},
+    },
+    delete: {
+      name: "Delete",
+      requestType: DeleteRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    find: {
+      name: "Find",
+      requestType: FindRequest,
+      requestStream: false,
+      responseType: FindResponse,
+      responseStream: false,
+      options: {},
+    },
+    update: {
+      name: "Update",
+      requestType: UpdateRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+  },
+} as const;
+
+declare var self: any | undefined;
+declare var window: any | undefined;
+declare var global: any | undefined;
+var globalThis: any = (() => {
+  if (typeof globalThis !== "undefined") return globalThis;
+  if (typeof self !== "undefined") return self;
+  if (typeof window !== "undefined") return window;
+  if (typeof global !== "undefined") return global;
+  throw "Unable to locate global object";
+})();
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
+
+function longToNumber(long: Long): number {
+  if (long.gt(Number.MAX_SAFE_INTEGER)) {
+    throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER");
+  }
+  return long.toNumber();
+}
+
+if (_m0.util.Long !== Long) {
+  _m0.util.Long = Long as any;
+  _m0.configure();
+}
diff --git a/clients/references/index.d.ts b/clients/references/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7237d457a3ea5c2266bb349811f2ea1194c6dab9
--- /dev/null
+++ b/clients/references/index.d.ts
@@ -0,0 +1,2 @@
+export * from './references';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/references/index.d.ts.map b/clients/references/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..94b29d0e51ee14cb82ffd367ba1c66408df7f8d4
--- /dev/null
+++ b/clients/references/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA"}
\ No newline at end of file
diff --git a/clients/references/index.js b/clients/references/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..97094d9d0fb7627f786e889b681a6100a7952ad0
--- /dev/null
+++ b/clients/references/index.js
@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./references"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/references/index.js.map b/clients/references/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..79630662e167d9a2cc68d70274e33c8de2e8fbdd
--- /dev/null
+++ b/clients/references/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA4B"}
\ No newline at end of file
diff --git a/clients/references/references.ts b/clients/references/references.ts
new file mode 100644
index 0000000000000000000000000000000000000000..509a606f77dbdf6f1e5a9da56dd453d3dd464a13
--- /dev/null
+++ b/clients/references/references.ts
@@ -0,0 +1,208 @@
+/* eslint-disable */
+import { Item } from "../items/items";
+import * as _m0 from "protobufjs/minimal";
+
+export interface Reference {
+  id: string;
+  collectionId: string;
+}
+
+export interface GetRequest {
+  spaceId: string;
+  envId: string;
+  references: Reference[];
+}
+
+export interface GetResponse {
+  items: Item[];
+  notfound: Reference[];
+}
+
+function createBaseReference(): Reference {
+  return { id: "", collectionId: "" };
+}
+
+export const Reference = {
+  encode(
+    message: Reference,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.id !== "") {
+      writer.uint32(10).string(message.id);
+    }
+    if (message.collectionId !== "") {
+      writer.uint32(18).string(message.collectionId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Reference {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseReference();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.id = reader.string();
+          break;
+        case 2:
+          message.collectionId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Reference>): Reference {
+    const message = createBaseReference();
+    message.id = object.id ?? "";
+    message.collectionId = object.collectionId ?? "";
+    return message;
+  },
+};
+
+function createBaseGetRequest(): GetRequest {
+  return { spaceId: "", envId: "", references: [] };
+}
+
+export const GetRequest = {
+  encode(
+    message: GetRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.envId !== "") {
+      writer.uint32(18).string(message.envId);
+    }
+    for (const v of message.references) {
+      Reference.encode(v!, writer.uint32(26).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.envId = reader.string();
+          break;
+        case 3:
+          message.references.push(Reference.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetRequest>): GetRequest {
+    const message = createBaseGetRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.envId = object.envId ?? "";
+    message.references =
+      object.references?.map((e) => Reference.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseGetResponse(): GetResponse {
+  return { items: [], notfound: [] };
+}
+
+export const GetResponse = {
+  encode(
+    message: GetResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.items) {
+      Item.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    for (const v of message.notfound) {
+      Reference.encode(v!, writer.uint32(18).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.items.push(Item.decode(reader, reader.uint32()));
+          break;
+        case 2:
+          message.notfound.push(Reference.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetResponse>): GetResponse {
+    const message = createBaseGetResponse();
+    message.items = object.items?.map((e) => Item.fromPartial(e)) || [];
+    message.notfound =
+      object.notfound?.map((e) => Reference.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+/**
+ * References принимает список ссылок на записи и возвращает два списка:
+ * список найденных записей и не найденных ссылок
+ */
+export type ReferencesDefinition = typeof ReferencesDefinition;
+export const ReferencesDefinition = {
+  name: "References",
+  fullName: "content.references.References",
+  methods: {
+    get: {
+      name: "Get",
+      requestType: GetRequest,
+      requestStream: false,
+      responseType: GetResponse,
+      responseStream: false,
+      options: {},
+    },
+  },
+} as const;
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
diff --git a/clients/roles/index.d.ts b/clients/roles/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..edaecec85b6b15af0416fa4946759f1fe0798e2f
--- /dev/null
+++ b/clients/roles/index.d.ts
@@ -0,0 +1,2 @@
+export * from './roles';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/roles/index.d.ts.map b/clients/roles/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..1f64580f3931037e5313efed7af9dcac3617d0bf
--- /dev/null
+++ b/clients/roles/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA"}
\ No newline at end of file
diff --git a/clients/roles/index.js b/clients/roles/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..cbe239baabfd2de27df44f073adc97e4ddd2b388
--- /dev/null
+++ b/clients/roles/index.js
@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./roles"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/roles/index.js.map b/clients/roles/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..3fef9d4fc40722278aba7d6931ba7465df482b28
--- /dev/null
+++ b/clients/roles/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAuB"}
\ No newline at end of file
diff --git a/clients/roles/roles.ts b/clients/roles/roles.ts
new file mode 100644
index 0000000000000000000000000000000000000000..04101dcbc9bdec3d641f2e533bb26a7793b8a84a
--- /dev/null
+++ b/clients/roles/roles.ts
@@ -0,0 +1,559 @@
+/* eslint-disable */
+import { Rule } from "../common/common";
+import { Empty } from "../google/protobuf/empty";
+import * as _m0 from "protobufjs/minimal";
+
+export interface Role {
+  /** Внутренний идентификатор роли */
+  id: string;
+  /** Идентификатор пространства */
+  spaceId: string;
+  /** Описание роли, назначение */
+  description: string;
+  /** Список правил доступа к коллекциям */
+  rules: Rule[];
+  /** Список доступных окружений (ID или Alias) */
+  environments: string[];
+  /**
+   * Разрешить доступ API управления:
+   * - Управление коллекциями
+   * - Управление приложениями
+   * - Управление ролями
+   * - Управление окружениями
+   * - Управление приглашениями
+   * - Управление locales
+   * - Управление участниками
+   */
+  allowManagement: boolean;
+}
+
+export interface CreateRequest {
+  role?: Role;
+}
+
+export interface CreateResponse {
+  created?: Role;
+}
+
+export interface GetRequest {
+  spaceId: string;
+  roleId: string;
+}
+
+export interface GetResponse {
+  role?: Role;
+}
+
+export interface UpdateRequest {
+  role?: Role;
+}
+
+export interface ListRequest {
+  spaceId: string;
+}
+
+export interface ListResponse {
+  roles: Role[];
+}
+
+export interface DeleteRequest {
+  spaceId: string;
+  roleId: string;
+}
+
+function createBaseRole(): Role {
+  return {
+    id: "",
+    spaceId: "",
+    description: "",
+    rules: [],
+    environments: [],
+    allowManagement: false,
+  };
+}
+
+export const Role = {
+  encode(message: Role, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
+    if (message.id !== "") {
+      writer.uint32(10).string(message.id);
+    }
+    if (message.spaceId !== "") {
+      writer.uint32(18).string(message.spaceId);
+    }
+    if (message.description !== "") {
+      writer.uint32(26).string(message.description);
+    }
+    for (const v of message.rules) {
+      Rule.encode(v!, writer.uint32(34).fork()).ldelim();
+    }
+    for (const v of message.environments) {
+      writer.uint32(42).string(v!);
+    }
+    if (message.allowManagement === true) {
+      writer.uint32(80).bool(message.allowManagement);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Role {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseRole();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.id = reader.string();
+          break;
+        case 2:
+          message.spaceId = reader.string();
+          break;
+        case 3:
+          message.description = reader.string();
+          break;
+        case 4:
+          message.rules.push(Rule.decode(reader, reader.uint32()));
+          break;
+        case 5:
+          message.environments.push(reader.string());
+          break;
+        case 10:
+          message.allowManagement = reader.bool();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Role>): Role {
+    const message = createBaseRole();
+    message.id = object.id ?? "";
+    message.spaceId = object.spaceId ?? "";
+    message.description = object.description ?? "";
+    message.rules = object.rules?.map((e) => Rule.fromPartial(e)) || [];
+    message.environments = object.environments?.map((e) => e) || [];
+    message.allowManagement = object.allowManagement ?? false;
+    return message;
+  },
+};
+
+function createBaseCreateRequest(): CreateRequest {
+  return { role: undefined };
+}
+
+export const CreateRequest = {
+  encode(
+    message: CreateRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.role !== undefined) {
+      Role.encode(message.role, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CreateRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCreateRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.role = Role.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CreateRequest>): CreateRequest {
+    const message = createBaseCreateRequest();
+    message.role =
+      object.role !== undefined && object.role !== null
+        ? Role.fromPartial(object.role)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseCreateResponse(): CreateResponse {
+  return { created: undefined };
+}
+
+export const CreateResponse = {
+  encode(
+    message: CreateResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.created !== undefined) {
+      Role.encode(message.created, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CreateResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCreateResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.created = Role.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CreateResponse>): CreateResponse {
+    const message = createBaseCreateResponse();
+    message.created =
+      object.created !== undefined && object.created !== null
+        ? Role.fromPartial(object.created)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseGetRequest(): GetRequest {
+  return { spaceId: "", roleId: "" };
+}
+
+export const GetRequest = {
+  encode(
+    message: GetRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.roleId !== "") {
+      writer.uint32(18).string(message.roleId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.roleId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetRequest>): GetRequest {
+    const message = createBaseGetRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.roleId = object.roleId ?? "";
+    return message;
+  },
+};
+
+function createBaseGetResponse(): GetResponse {
+  return { role: undefined };
+}
+
+export const GetResponse = {
+  encode(
+    message: GetResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.role !== undefined) {
+      Role.encode(message.role, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.role = Role.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetResponse>): GetResponse {
+    const message = createBaseGetResponse();
+    message.role =
+      object.role !== undefined && object.role !== null
+        ? Role.fromPartial(object.role)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseUpdateRequest(): UpdateRequest {
+  return { role: undefined };
+}
+
+export const UpdateRequest = {
+  encode(
+    message: UpdateRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.role !== undefined) {
+      Role.encode(message.role, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UpdateRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUpdateRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.role = Role.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UpdateRequest>): UpdateRequest {
+    const message = createBaseUpdateRequest();
+    message.role =
+      object.role !== undefined && object.role !== null
+        ? Role.fromPartial(object.role)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseListRequest(): ListRequest {
+  return { spaceId: "" };
+}
+
+export const ListRequest = {
+  encode(
+    message: ListRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ListRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListRequest>): ListRequest {
+    const message = createBaseListRequest();
+    message.spaceId = object.spaceId ?? "";
+    return message;
+  },
+};
+
+function createBaseListResponse(): ListResponse {
+  return { roles: [] };
+}
+
+export const ListResponse = {
+  encode(
+    message: ListResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.roles) {
+      Role.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ListResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.roles.push(Role.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListResponse>): ListResponse {
+    const message = createBaseListResponse();
+    message.roles = object.roles?.map((e) => Role.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseDeleteRequest(): DeleteRequest {
+  return { spaceId: "", roleId: "" };
+}
+
+export const DeleteRequest = {
+  encode(
+    message: DeleteRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.roleId !== "") {
+      writer.uint32(18).string(message.roleId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): DeleteRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseDeleteRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.roleId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<DeleteRequest>): DeleteRequest {
+    const message = createBaseDeleteRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.roleId = object.roleId ?? "";
+    return message;
+  },
+};
+
+export type RolesDefinition = typeof RolesDefinition;
+export const RolesDefinition = {
+  name: "Roles",
+  fullName: "content.roles.Roles",
+  methods: {
+    /** Create - создает роль в рамках пространства */
+    create: {
+      name: "Create",
+      requestType: CreateRequest,
+      requestStream: false,
+      responseType: CreateResponse,
+      responseStream: false,
+      options: {},
+    },
+    /** Get - возвращает роль по id */
+    get: {
+      name: "Get",
+      requestType: GetRequest,
+      requestStream: false,
+      responseType: GetResponse,
+      responseStream: false,
+      options: {},
+    },
+    /** Update - обновляет параметры роли */
+    update: {
+      name: "Update",
+      requestType: UpdateRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    /** List - возвращает список ролей, созданных в пространстве */
+    list: {
+      name: "List",
+      requestType: ListRequest,
+      requestStream: false,
+      responseType: ListResponse,
+      responseStream: false,
+      options: {},
+    },
+    /** Delete - удаляет указанную роль из пространстве */
+    delete: {
+      name: "Delete",
+      requestType: DeleteRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+  },
+} as const;
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
diff --git a/clients/spaces/index.d.ts b/clients/spaces/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9b0511b8416c26908b405ae48b5da41744256565
--- /dev/null
+++ b/clients/spaces/index.d.ts
@@ -0,0 +1,2 @@
+export * from './spaces';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/spaces/index.d.ts.map b/clients/spaces/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..d68da9bfd6c9e0e766776d648d711c343fde236c
--- /dev/null
+++ b/clients/spaces/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA"}
\ No newline at end of file
diff --git a/clients/spaces/index.js b/clients/spaces/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..6df6a8a2560a204656e80837e99f232fd22f9d15
--- /dev/null
+++ b/clients/spaces/index.js
@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./spaces"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/spaces/index.js.map b/clients/spaces/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..9a82574a46940f84df0cf1940e8c3b0bab8d91ef
--- /dev/null
+++ b/clients/spaces/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAwB"}
\ No newline at end of file
diff --git a/clients/spaces/spaces.ts b/clients/spaces/spaces.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4f306a13450e56c252342fb0658c7bf3e078b488
--- /dev/null
+++ b/clients/spaces/spaces.ts
@@ -0,0 +1,644 @@
+/* eslint-disable */
+import { Empty } from "../google/protobuf/empty";
+import * as _m0 from "protobufjs/minimal";
+
+export enum State {
+  UNKNOWN = 0,
+  NEW = 1,
+  READY = 2,
+  PREPARING = 3,
+  MAINTENANCE = 4,
+  MIGRATION = 5,
+  DELETING = 6,
+  ERROR = 7,
+  UNRECOGNIZED = -1,
+}
+
+export interface Space {
+  id: string;
+  orgId: string;
+  name: string;
+  description: string;
+  state: State;
+  config?: Config;
+}
+
+export interface Config {
+  features: string[];
+}
+
+export interface CreateRequest {
+  space?: Space;
+}
+
+export interface CreateResponse {
+  created?: Space;
+}
+
+export interface GetRequest {
+  spaceId: string;
+}
+
+export interface GetResponse {
+  space?: Space;
+}
+
+export interface ListRequest {
+  orgId: string;
+}
+
+export interface ListResponse {
+  spaces: Space[];
+}
+
+export interface UpdateRequest {
+  space?: Space;
+}
+
+export interface UpdateConfigRequest {
+  spaceId: string;
+  config?: Config;
+}
+
+export interface DeleteRequest {
+  spaceId: string;
+}
+
+function createBaseSpace(): Space {
+  return {
+    id: "",
+    orgId: "",
+    name: "",
+    description: "",
+    state: 0,
+    config: undefined,
+  };
+}
+
+export const Space = {
+  encode(message: Space, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
+    if (message.id !== "") {
+      writer.uint32(10).string(message.id);
+    }
+    if (message.orgId !== "") {
+      writer.uint32(18).string(message.orgId);
+    }
+    if (message.name !== "") {
+      writer.uint32(26).string(message.name);
+    }
+    if (message.description !== "") {
+      writer.uint32(34).string(message.description);
+    }
+    if (message.state !== 0) {
+      writer.uint32(40).int32(message.state);
+    }
+    if (message.config !== undefined) {
+      Config.encode(message.config, writer.uint32(82).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Space {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseSpace();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.id = reader.string();
+          break;
+        case 2:
+          message.orgId = reader.string();
+          break;
+        case 3:
+          message.name = reader.string();
+          break;
+        case 4:
+          message.description = reader.string();
+          break;
+        case 5:
+          message.state = reader.int32() as any;
+          break;
+        case 10:
+          message.config = Config.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Space>): Space {
+    const message = createBaseSpace();
+    message.id = object.id ?? "";
+    message.orgId = object.orgId ?? "";
+    message.name = object.name ?? "";
+    message.description = object.description ?? "";
+    message.state = object.state ?? 0;
+    message.config =
+      object.config !== undefined && object.config !== null
+        ? Config.fromPartial(object.config)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseConfig(): Config {
+  return { features: [] };
+}
+
+export const Config = {
+  encode(
+    message: Config,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.features) {
+      writer.uint32(10).string(v!);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Config {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseConfig();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.features.push(reader.string());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Config>): Config {
+    const message = createBaseConfig();
+    message.features = object.features?.map((e) => e) || [];
+    return message;
+  },
+};
+
+function createBaseCreateRequest(): CreateRequest {
+  return { space: undefined };
+}
+
+export const CreateRequest = {
+  encode(
+    message: CreateRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.space !== undefined) {
+      Space.encode(message.space, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CreateRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCreateRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.space = Space.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CreateRequest>): CreateRequest {
+    const message = createBaseCreateRequest();
+    message.space =
+      object.space !== undefined && object.space !== null
+        ? Space.fromPartial(object.space)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseCreateResponse(): CreateResponse {
+  return { created: undefined };
+}
+
+export const CreateResponse = {
+  encode(
+    message: CreateResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.created !== undefined) {
+      Space.encode(message.created, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CreateResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCreateResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.created = Space.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CreateResponse>): CreateResponse {
+    const message = createBaseCreateResponse();
+    message.created =
+      object.created !== undefined && object.created !== null
+        ? Space.fromPartial(object.created)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseGetRequest(): GetRequest {
+  return { spaceId: "" };
+}
+
+export const GetRequest = {
+  encode(
+    message: GetRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetRequest>): GetRequest {
+    const message = createBaseGetRequest();
+    message.spaceId = object.spaceId ?? "";
+    return message;
+  },
+};
+
+function createBaseGetResponse(): GetResponse {
+  return { space: undefined };
+}
+
+export const GetResponse = {
+  encode(
+    message: GetResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.space !== undefined) {
+      Space.encode(message.space, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.space = Space.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetResponse>): GetResponse {
+    const message = createBaseGetResponse();
+    message.space =
+      object.space !== undefined && object.space !== null
+        ? Space.fromPartial(object.space)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseListRequest(): ListRequest {
+  return { orgId: "" };
+}
+
+export const ListRequest = {
+  encode(
+    message: ListRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.orgId !== "") {
+      writer.uint32(10).string(message.orgId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ListRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.orgId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListRequest>): ListRequest {
+    const message = createBaseListRequest();
+    message.orgId = object.orgId ?? "";
+    return message;
+  },
+};
+
+function createBaseListResponse(): ListResponse {
+  return { spaces: [] };
+}
+
+export const ListResponse = {
+  encode(
+    message: ListResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.spaces) {
+      Space.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): ListResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseListResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaces.push(Space.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<ListResponse>): ListResponse {
+    const message = createBaseListResponse();
+    message.spaces = object.spaces?.map((e) => Space.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+function createBaseUpdateRequest(): UpdateRequest {
+  return { space: undefined };
+}
+
+export const UpdateRequest = {
+  encode(
+    message: UpdateRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.space !== undefined) {
+      Space.encode(message.space, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UpdateRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUpdateRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.space = Space.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UpdateRequest>): UpdateRequest {
+    const message = createBaseUpdateRequest();
+    message.space =
+      object.space !== undefined && object.space !== null
+        ? Space.fromPartial(object.space)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseUpdateConfigRequest(): UpdateConfigRequest {
+  return { spaceId: "", config: undefined };
+}
+
+export const UpdateConfigRequest = {
+  encode(
+    message: UpdateConfigRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    if (message.config !== undefined) {
+      Config.encode(message.config, writer.uint32(18).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UpdateConfigRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUpdateConfigRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        case 2:
+          message.config = Config.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UpdateConfigRequest>): UpdateConfigRequest {
+    const message = createBaseUpdateConfigRequest();
+    message.spaceId = object.spaceId ?? "";
+    message.config =
+      object.config !== undefined && object.config !== null
+        ? Config.fromPartial(object.config)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseDeleteRequest(): DeleteRequest {
+  return { spaceId: "" };
+}
+
+export const DeleteRequest = {
+  encode(
+    message: DeleteRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.spaceId !== "") {
+      writer.uint32(10).string(message.spaceId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): DeleteRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseDeleteRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.spaceId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<DeleteRequest>): DeleteRequest {
+    const message = createBaseDeleteRequest();
+    message.spaceId = object.spaceId ?? "";
+    return message;
+  },
+};
+
+export type SpacesDefinition = typeof SpacesDefinition;
+export const SpacesDefinition = {
+  name: "Spaces",
+  fullName: "content.spaces.Spaces",
+  methods: {
+    create: {
+      name: "Create",
+      requestType: CreateRequest,
+      requestStream: false,
+      responseType: CreateResponse,
+      responseStream: false,
+      options: {},
+    },
+    get: {
+      name: "Get",
+      requestType: GetRequest,
+      requestStream: false,
+      responseType: GetResponse,
+      responseStream: false,
+      options: {},
+    },
+    list: {
+      name: "List",
+      requestType: ListRequest,
+      requestStream: false,
+      responseType: ListResponse,
+      responseStream: false,
+      options: {},
+    },
+    update: {
+      name: "Update",
+      requestType: UpdateRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    updateConfig: {
+      name: "UpdateConfig",
+      requestType: UpdateConfigRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    delete: {
+      name: "Delete",
+      requestType: DeleteRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+  },
+} as const;
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
diff --git a/clients/status/index.d.ts b/clients/status/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b71fe88243d3dcdc258f9d1210e7c74c55f89770
--- /dev/null
+++ b/clients/status/index.d.ts
@@ -0,0 +1,2 @@
+export * from './status';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/status/index.d.ts.map b/clients/status/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..d68da9bfd6c9e0e766776d648d711c343fde236c
--- /dev/null
+++ b/clients/status/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA"}
\ No newline at end of file
diff --git a/clients/status/index.js b/clients/status/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..73b5778ec39174f0bb23706d8ece2fa0ead60703
--- /dev/null
+++ b/clients/status/index.js
@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./status"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/status/index.js.map b/clients/status/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..9a82574a46940f84df0cf1940e8c3b0bab8d91ef
--- /dev/null
+++ b/clients/status/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAwB"}
\ No newline at end of file
diff --git a/clients/status/status.ts b/clients/status/status.ts
new file mode 100644
index 0000000000000000000000000000000000000000..25f08f0f17900e3fdf2d3f44d74faa1428054967
--- /dev/null
+++ b/clients/status/status.ts
@@ -0,0 +1,146 @@
+/* eslint-disable */
+import { Any } from "../google/protobuf/any";
+import * as _m0 from "protobufjs/minimal";
+
+/**
+ * The `Status` type defines a logical error model that is suitable for different
+ * programming environments, including REST APIs and RPC APIs. It is used by
+ * [gRPC](https://github.com/grpc). The error model is designed to be:
+ *
+ * - Simple to use and understand for most users
+ * - Flexible enough to meet unexpected needs
+ *
+ * # Overview
+ *
+ * The `Status` message contains three pieces of data: error code, error message,
+ * and error details. The error code should be an enum value of
+ * [google.rpc.Code][google.rpc.Code], but it may accept additional error codes if needed.  The
+ * error message should be a developer-facing English message that helps
+ * developers *understand* and *resolve* the error. If a localized user-facing
+ * error message is needed, put the localized message in the error details or
+ * localize it in the client. The optional error details may contain arbitrary
+ * information about the error. There is a predefined set of error detail types
+ * in the package `google.rpc` which can be used for common error conditions.
+ *
+ * # Language mapping
+ *
+ * The `Status` message is the logical representation of the error model, but it
+ * is not necessarily the actual wire format. When the `Status` message is
+ * exposed in different client libraries and different wire protocols, it can be
+ * mapped differently. For example, it will likely be mapped to some exceptions
+ * in Java, but more likely mapped to some error codes in C.
+ *
+ * # Other uses
+ *
+ * The error model and the `Status` message can be used in a variety of
+ * environments, either with or without APIs, to provide a
+ * consistent developer experience across different environments.
+ *
+ * Example uses of this error model include:
+ *
+ * - Partial errors. If a service needs to return partial errors to the client,
+ *     it may embed the `Status` in the normal response to indicate the partial
+ *     errors.
+ *
+ * - Workflow errors. A typical workflow has multiple steps. Each step may
+ *     have a `Status` message for error reporting purpose.
+ *
+ * - Batch operations. If a client uses batch request and batch response, the
+ *     `Status` message should be used directly inside batch response, one for
+ *     each error sub-response.
+ *
+ * - Asynchronous operations. If an API call embeds asynchronous operation
+ *     results in its response, the status of those operations should be
+ *     represented directly using the `Status` message.
+ *
+ * - Logging. If some API errors are stored in logs, the message `Status` could
+ *     be used directly after any stripping needed for security/privacy reasons.
+ */
+export interface Status {
+  /** The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. */
+  code: number;
+  /**
+   * A developer-facing error message, which should be in English. Any
+   * user-facing error message should be localized and sent in the
+   * [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.
+   */
+  message: string;
+  /**
+   * A list of messages that carry the error details.  There will be a
+   * common set of message types for APIs to use.
+   */
+  details: Any[];
+}
+
+function createBaseStatus(): Status {
+  return { code: 0, message: "", details: [] };
+}
+
+export const Status = {
+  encode(
+    message: Status,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.code !== 0) {
+      writer.uint32(8).int32(message.code);
+    }
+    if (message.message !== "") {
+      writer.uint32(18).string(message.message);
+    }
+    for (const v of message.details) {
+      Any.encode(v!, writer.uint32(26).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Status {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseStatus();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.code = reader.int32();
+          break;
+        case 2:
+          message.message = reader.string();
+          break;
+        case 3:
+          message.details.push(Any.decode(reader, reader.uint32()));
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Status>): Status {
+    const message = createBaseStatus();
+    message.code = object.code ?? 0;
+    message.message = object.message ?? "";
+    message.details = object.details?.map((e) => Any.fromPartial(e)) || [];
+    return message;
+  },
+};
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
diff --git a/clients/users/index.d.ts b/clients/users/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..03dd625b0366e3680e5bbfdea6acdf56482577f8
--- /dev/null
+++ b/clients/users/index.d.ts
@@ -0,0 +1,2 @@
+export * from './users';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/users/index.d.ts.map b/clients/users/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..1f64580f3931037e5313efed7af9dcac3617d0bf
--- /dev/null
+++ b/clients/users/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA"}
\ No newline at end of file
diff --git a/clients/users/index.js b/clients/users/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..f2b4db925ef44b08de1303c2ab0077b5f89d15e0
--- /dev/null
+++ b/clients/users/index.js
@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./users"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/users/index.js.map b/clients/users/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..3fef9d4fc40722278aba7d6931ba7465df482b28
--- /dev/null
+++ b/clients/users/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAuB"}
\ No newline at end of file
diff --git a/clients/users/users.ts b/clients/users/users.ts
new file mode 100644
index 0000000000000000000000000000000000000000..68942617de9125fabe11d6f1b5e9d3a76c1afb15
--- /dev/null
+++ b/clients/users/users.ts
@@ -0,0 +1,842 @@
+/* eslint-disable */
+import { FindOptions } from "../common/common";
+import Long from "long";
+import { Empty } from "../google/protobuf/empty";
+import * as _m0 from "protobufjs/minimal";
+import { BoolValue } from "../google/protobuf/wrappers";
+
+export interface User {
+  /** Уникальный идентификатор, присваивается системой */
+  id: string;
+  /** Уникальное имя, login */
+  name: string;
+  /** Authorization subjects (JWT sub claims) */
+  identities: string[];
+  /** Имя пользователя для отображения */
+  displayName: string;
+  /** Email, указывается пользователем */
+  email: string;
+  /** Флаг что email проверен */
+  emailVerified?: boolean;
+  /** URI изображения пользователя */
+  avatarUrl: string;
+  /** Системный пользователь (может получать доступ к расширенному API) */
+  system?: boolean;
+}
+
+export interface Filter {
+  id: string[];
+  name: string[];
+  identities: string[];
+  displayName: string[];
+  email: string[];
+  emailVerified?: boolean;
+  system?: boolean;
+}
+
+export interface CreateRequest {
+  create?: User;
+}
+
+export interface CreateResponse {
+  user?: User;
+}
+
+/** userId = `current` для получения текущего пользователя */
+export interface GetRequest {
+  userId: string;
+}
+
+export interface GetResponse {
+  user?: User;
+}
+
+export interface FindRequest {
+  filter?: Filter;
+  options?: FindOptions;
+}
+
+export interface FindResponse {
+  users: User[];
+  total: number;
+}
+
+/** userId = `current` для обновления текущего пользователя */
+export interface UpdateRequest {
+  /** Содержит только поля необходимые для обновления */
+  update?: User;
+}
+
+export interface DeleteRequest {
+  userId: string;
+}
+
+export interface GetByIdentityRequest {
+  identity: string;
+}
+
+export interface GetByIdentityResponse {
+  user?: User;
+}
+
+function createBaseUser(): User {
+  return {
+    id: "",
+    name: "",
+    identities: [],
+    displayName: "",
+    email: "",
+    emailVerified: undefined,
+    avatarUrl: "",
+    system: undefined,
+  };
+}
+
+export const User = {
+  encode(message: User, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
+    if (message.id !== "") {
+      writer.uint32(10).string(message.id);
+    }
+    if (message.name !== "") {
+      writer.uint32(18).string(message.name);
+    }
+    for (const v of message.identities) {
+      writer.uint32(26).string(v!);
+    }
+    if (message.displayName !== "") {
+      writer.uint32(34).string(message.displayName);
+    }
+    if (message.email !== "") {
+      writer.uint32(42).string(message.email);
+    }
+    if (message.emailVerified !== undefined) {
+      BoolValue.encode(
+        { value: message.emailVerified! },
+        writer.uint32(50).fork()
+      ).ldelim();
+    }
+    if (message.avatarUrl !== "") {
+      writer.uint32(58).string(message.avatarUrl);
+    }
+    if (message.system !== undefined) {
+      BoolValue.encode(
+        { value: message.system! },
+        writer.uint32(82).fork()
+      ).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): User {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUser();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.id = reader.string();
+          break;
+        case 2:
+          message.name = reader.string();
+          break;
+        case 3:
+          message.identities.push(reader.string());
+          break;
+        case 4:
+          message.displayName = reader.string();
+          break;
+        case 5:
+          message.email = reader.string();
+          break;
+        case 6:
+          message.emailVerified = BoolValue.decode(
+            reader,
+            reader.uint32()
+          ).value;
+          break;
+        case 7:
+          message.avatarUrl = reader.string();
+          break;
+        case 10:
+          message.system = BoolValue.decode(reader, reader.uint32()).value;
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<User>): User {
+    const message = createBaseUser();
+    message.id = object.id ?? "";
+    message.name = object.name ?? "";
+    message.identities = object.identities?.map((e) => e) || [];
+    message.displayName = object.displayName ?? "";
+    message.email = object.email ?? "";
+    message.emailVerified = object.emailVerified ?? undefined;
+    message.avatarUrl = object.avatarUrl ?? "";
+    message.system = object.system ?? undefined;
+    return message;
+  },
+};
+
+function createBaseFilter(): Filter {
+  return {
+    id: [],
+    name: [],
+    identities: [],
+    displayName: [],
+    email: [],
+    emailVerified: undefined,
+    system: undefined,
+  };
+}
+
+export const Filter = {
+  encode(
+    message: Filter,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.id) {
+      writer.uint32(10).string(v!);
+    }
+    for (const v of message.name) {
+      writer.uint32(18).string(v!);
+    }
+    for (const v of message.identities) {
+      writer.uint32(26).string(v!);
+    }
+    for (const v of message.displayName) {
+      writer.uint32(34).string(v!);
+    }
+    for (const v of message.email) {
+      writer.uint32(42).string(v!);
+    }
+    if (message.emailVerified !== undefined) {
+      BoolValue.encode(
+        { value: message.emailVerified! },
+        writer.uint32(50).fork()
+      ).ldelim();
+    }
+    if (message.system !== undefined) {
+      BoolValue.encode(
+        { value: message.system! },
+        writer.uint32(82).fork()
+      ).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): Filter {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFilter();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.id.push(reader.string());
+          break;
+        case 2:
+          message.name.push(reader.string());
+          break;
+        case 3:
+          message.identities.push(reader.string());
+          break;
+        case 4:
+          message.displayName.push(reader.string());
+          break;
+        case 5:
+          message.email.push(reader.string());
+          break;
+        case 6:
+          message.emailVerified = BoolValue.decode(
+            reader,
+            reader.uint32()
+          ).value;
+          break;
+        case 10:
+          message.system = BoolValue.decode(reader, reader.uint32()).value;
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<Filter>): Filter {
+    const message = createBaseFilter();
+    message.id = object.id?.map((e) => e) || [];
+    message.name = object.name?.map((e) => e) || [];
+    message.identities = object.identities?.map((e) => e) || [];
+    message.displayName = object.displayName?.map((e) => e) || [];
+    message.email = object.email?.map((e) => e) || [];
+    message.emailVerified = object.emailVerified ?? undefined;
+    message.system = object.system ?? undefined;
+    return message;
+  },
+};
+
+function createBaseCreateRequest(): CreateRequest {
+  return { create: undefined };
+}
+
+export const CreateRequest = {
+  encode(
+    message: CreateRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.create !== undefined) {
+      User.encode(message.create, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CreateRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCreateRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.create = User.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CreateRequest>): CreateRequest {
+    const message = createBaseCreateRequest();
+    message.create =
+      object.create !== undefined && object.create !== null
+        ? User.fromPartial(object.create)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseCreateResponse(): CreateResponse {
+  return { user: undefined };
+}
+
+export const CreateResponse = {
+  encode(
+    message: CreateResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.user !== undefined) {
+      User.encode(message.user, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): CreateResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseCreateResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.user = User.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<CreateResponse>): CreateResponse {
+    const message = createBaseCreateResponse();
+    message.user =
+      object.user !== undefined && object.user !== null
+        ? User.fromPartial(object.user)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseGetRequest(): GetRequest {
+  return { userId: "" };
+}
+
+export const GetRequest = {
+  encode(
+    message: GetRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.userId !== "") {
+      writer.uint32(10).string(message.userId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.userId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetRequest>): GetRequest {
+    const message = createBaseGetRequest();
+    message.userId = object.userId ?? "";
+    return message;
+  },
+};
+
+function createBaseGetResponse(): GetResponse {
+  return { user: undefined };
+}
+
+export const GetResponse = {
+  encode(
+    message: GetResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.user !== undefined) {
+      User.encode(message.user, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.user = User.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetResponse>): GetResponse {
+    const message = createBaseGetResponse();
+    message.user =
+      object.user !== undefined && object.user !== null
+        ? User.fromPartial(object.user)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseFindRequest(): FindRequest {
+  return { filter: undefined, options: undefined };
+}
+
+export const FindRequest = {
+  encode(
+    message: FindRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.filter !== undefined) {
+      Filter.encode(message.filter, writer.uint32(10).fork()).ldelim();
+    }
+    if (message.options !== undefined) {
+      FindOptions.encode(message.options, writer.uint32(82).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): FindRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFindRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.filter = Filter.decode(reader, reader.uint32());
+          break;
+        case 10:
+          message.options = FindOptions.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<FindRequest>): FindRequest {
+    const message = createBaseFindRequest();
+    message.filter =
+      object.filter !== undefined && object.filter !== null
+        ? Filter.fromPartial(object.filter)
+        : undefined;
+    message.options =
+      object.options !== undefined && object.options !== null
+        ? FindOptions.fromPartial(object.options)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseFindResponse(): FindResponse {
+  return { users: [], total: 0 };
+}
+
+export const FindResponse = {
+  encode(
+    message: FindResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    for (const v of message.users) {
+      User.encode(v!, writer.uint32(10).fork()).ldelim();
+    }
+    if (message.total !== 0) {
+      writer.uint32(16).int64(message.total);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): FindResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseFindResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.users.push(User.decode(reader, reader.uint32()));
+          break;
+        case 2:
+          message.total = longToNumber(reader.int64() as Long);
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<FindResponse>): FindResponse {
+    const message = createBaseFindResponse();
+    message.users = object.users?.map((e) => User.fromPartial(e)) || [];
+    message.total = object.total ?? 0;
+    return message;
+  },
+};
+
+function createBaseUpdateRequest(): UpdateRequest {
+  return { update: undefined };
+}
+
+export const UpdateRequest = {
+  encode(
+    message: UpdateRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.update !== undefined) {
+      User.encode(message.update, writer.uint32(18).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): UpdateRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseUpdateRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 2:
+          message.update = User.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<UpdateRequest>): UpdateRequest {
+    const message = createBaseUpdateRequest();
+    message.update =
+      object.update !== undefined && object.update !== null
+        ? User.fromPartial(object.update)
+        : undefined;
+    return message;
+  },
+};
+
+function createBaseDeleteRequest(): DeleteRequest {
+  return { userId: "" };
+}
+
+export const DeleteRequest = {
+  encode(
+    message: DeleteRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.userId !== "") {
+      writer.uint32(10).string(message.userId);
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): DeleteRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseDeleteRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.userId = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<DeleteRequest>): DeleteRequest {
+    const message = createBaseDeleteRequest();
+    message.userId = object.userId ?? "";
+    return message;
+  },
+};
+
+function createBaseGetByIdentityRequest(): GetByIdentityRequest {
+  return { identity: "" };
+}
+
+export const GetByIdentityRequest = {
+  encode(
+    message: GetByIdentityRequest,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.identity !== "") {
+      writer.uint32(10).string(message.identity);
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): GetByIdentityRequest {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetByIdentityRequest();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.identity = reader.string();
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetByIdentityRequest>): GetByIdentityRequest {
+    const message = createBaseGetByIdentityRequest();
+    message.identity = object.identity ?? "";
+    return message;
+  },
+};
+
+function createBaseGetByIdentityResponse(): GetByIdentityResponse {
+  return { user: undefined };
+}
+
+export const GetByIdentityResponse = {
+  encode(
+    message: GetByIdentityResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.user !== undefined) {
+      User.encode(message.user, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(
+    input: _m0.Reader | Uint8Array,
+    length?: number
+  ): GetByIdentityResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetByIdentityResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.user = User.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(
+    object: DeepPartial<GetByIdentityResponse>
+  ): GetByIdentityResponse {
+    const message = createBaseGetByIdentityResponse();
+    message.user =
+      object.user !== undefined && object.user !== null
+        ? User.fromPartial(object.user)
+        : undefined;
+    return message;
+  },
+};
+
+export type UsersDefinition = typeof UsersDefinition;
+export const UsersDefinition = {
+  name: "Users",
+  fullName: "account.users.Users",
+  methods: {
+    /** Создание пользователя или регистрация текущего пользователя в системе, если create.id == `current` */
+    create: {
+      name: "Create",
+      requestType: CreateRequest,
+      requestStream: false,
+      responseType: CreateResponse,
+      responseStream: false,
+      options: {},
+    },
+    /**
+     * - Получение любого пользователя по идентификатору
+     *  - Получение текущего (от лица которого делается запрос) пользователя по специальному идентификатору `current`
+     */
+    get: {
+      name: "Get",
+      requestType: GetRequest,
+      requestStream: false,
+      responseType: GetResponse,
+      responseStream: false,
+      options: {},
+    },
+    /** Найти пользователей с фильтрацией. Фильтры доступны пользователям в зависимости от их прав */
+    find: {
+      name: "Find",
+      requestType: FindRequest,
+      requestStream: false,
+      responseType: FindResponse,
+      responseStream: false,
+      options: {},
+    },
+    /**
+     * - Обновление существующего пользователя по идентификатору
+     *  - Обновление текущего пользователя по спец. идентификатору `current`
+     */
+    update: {
+      name: "Update",
+      requestType: UpdateRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    /**
+     * - Удаление существующего пользователя по идентификатору
+     *  - Удаление текущего пользователя по спец. идентификатору `current`
+     */
+    delete: {
+      name: "Delete",
+      requestType: DeleteRequest,
+      requestStream: false,
+      responseType: Empty,
+      responseStream: false,
+      options: {},
+    },
+    /**
+     * Метод для внутреннего использования. Недоступен для внешних
+     * запросов - авторизация вернет ошибку `access denied`
+     */
+    getByIdentity: {
+      name: "GetByIdentity",
+      requestType: GetByIdentityRequest,
+      requestStream: false,
+      responseType: GetByIdentityResponse,
+      responseStream: false,
+      options: {},
+    },
+  },
+} as const;
+
+declare var self: any | undefined;
+declare var window: any | undefined;
+declare var global: any | undefined;
+var globalThis: any = (() => {
+  if (typeof globalThis !== "undefined") return globalThis;
+  if (typeof self !== "undefined") return self;
+  if (typeof window !== "undefined") return window;
+  if (typeof global !== "undefined") return global;
+  throw "Unable to locate global object";
+})();
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
+
+function longToNumber(long: Long): number {
+  if (long.gt(Number.MAX_SAFE_INTEGER)) {
+    throw new globalThis.Error("Value is larger than Number.MAX_SAFE_INTEGER");
+  }
+  return long.toNumber();
+}
+
+if (_m0.util.Long !== Long) {
+  _m0.util.Long = Long as any;
+  _m0.configure();
+}
diff --git a/clients/versions/account/index.d.ts b/clients/versions/account/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bbdb51972306480c72f0fc8774a3fd132a4f99b9
--- /dev/null
+++ b/clients/versions/account/index.d.ts
@@ -0,0 +1,2 @@
+export * from './versions';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/versions/account/index.d.ts.map b/clients/versions/account/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..81d14ab63768aa15896ab5e29a575183d48308ac
--- /dev/null
+++ b/clients/versions/account/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA"}
\ No newline at end of file
diff --git a/clients/versions/account/index.js b/clients/versions/account/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..4adb464a326423194d859e53c8a9060f460e7c59
--- /dev/null
+++ b/clients/versions/account/index.js
@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./versions"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/versions/account/index.js.map b/clients/versions/account/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..5f0a1275bea7fe5d714e71a9f52bc00734a23e62
--- /dev/null
+++ b/clients/versions/account/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6CAA0B"}
\ No newline at end of file
diff --git a/clients/versions/account/versions.ts b/clients/versions/account/versions.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9870e0ad7e3ce5b2e6656cb4ba6894825e66c870
--- /dev/null
+++ b/clients/versions/account/versions.ts
@@ -0,0 +1,86 @@
+/* eslint-disable */
+import { Version } from "../../common/common";
+import { Empty } from "../../google/protobuf/empty";
+import * as _m0 from "protobufjs/minimal";
+
+export interface GetResponse {
+  version?: Version;
+}
+
+function createBaseGetResponse(): GetResponse {
+  return { version: undefined };
+}
+
+export const GetResponse = {
+  encode(
+    message: GetResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.version !== undefined) {
+      Version.encode(message.version, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.version = Version.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetResponse>): GetResponse {
+    const message = createBaseGetResponse();
+    message.version =
+      object.version !== undefined && object.version !== null
+        ? Version.fromPartial(object.version)
+        : undefined;
+    return message;
+  },
+};
+
+export type VersionsDefinition = typeof VersionsDefinition;
+export const VersionsDefinition = {
+  name: "Versions",
+  fullName: "account.Versions",
+  methods: {
+    get: {
+      name: "Get",
+      requestType: Empty,
+      requestStream: false,
+      responseType: GetResponse,
+      responseStream: false,
+      options: {},
+    },
+  },
+} as const;
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
diff --git a/clients/versions/content/index.d.ts b/clients/versions/content/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bbdb51972306480c72f0fc8774a3fd132a4f99b9
--- /dev/null
+++ b/clients/versions/content/index.d.ts
@@ -0,0 +1,2 @@
+export * from './versions';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/versions/content/index.d.ts.map b/clients/versions/content/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..81d14ab63768aa15896ab5e29a575183d48308ac
--- /dev/null
+++ b/clients/versions/content/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA"}
\ No newline at end of file
diff --git a/clients/versions/content/index.js b/clients/versions/content/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..4adb464a326423194d859e53c8a9060f460e7c59
--- /dev/null
+++ b/clients/versions/content/index.js
@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./versions"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/versions/content/index.js.map b/clients/versions/content/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..5f0a1275bea7fe5d714e71a9f52bc00734a23e62
--- /dev/null
+++ b/clients/versions/content/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6CAA0B"}
\ No newline at end of file
diff --git a/clients/versions/content/versions.ts b/clients/versions/content/versions.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4e2978ede17bce86ecdd4ff5c353c3d732552970
--- /dev/null
+++ b/clients/versions/content/versions.ts
@@ -0,0 +1,86 @@
+/* eslint-disable */
+import { Version } from "../../common/common";
+import { Empty } from "../../google/protobuf/empty";
+import * as _m0 from "protobufjs/minimal";
+
+export interface GetResponse {
+  version?: Version;
+}
+
+function createBaseGetResponse(): GetResponse {
+  return { version: undefined };
+}
+
+export const GetResponse = {
+  encode(
+    message: GetResponse,
+    writer: _m0.Writer = _m0.Writer.create()
+  ): _m0.Writer {
+    if (message.version !== undefined) {
+      Version.encode(message.version, writer.uint32(10).fork()).ldelim();
+    }
+    return writer;
+  },
+
+  decode(input: _m0.Reader | Uint8Array, length?: number): GetResponse {
+    const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input);
+    let end = length === undefined ? reader.len : reader.pos + length;
+    const message = createBaseGetResponse();
+    while (reader.pos < end) {
+      const tag = reader.uint32();
+      switch (tag >>> 3) {
+        case 1:
+          message.version = Version.decode(reader, reader.uint32());
+          break;
+        default:
+          reader.skipType(tag & 7);
+          break;
+      }
+    }
+    return message;
+  },
+
+  fromPartial(object: DeepPartial<GetResponse>): GetResponse {
+    const message = createBaseGetResponse();
+    message.version =
+      object.version !== undefined && object.version !== null
+        ? Version.fromPartial(object.version)
+        : undefined;
+    return message;
+  },
+};
+
+export type VersionsDefinition = typeof VersionsDefinition;
+export const VersionsDefinition = {
+  name: "Versions",
+  fullName: "content.Versions",
+  methods: {
+    get: {
+      name: "Get",
+      requestType: Empty,
+      requestStream: false,
+      responseType: GetResponse,
+      responseStream: false,
+      options: {},
+    },
+  },
+} as const;
+
+type Builtin =
+  | Date
+  | Function
+  | Uint8Array
+  | string
+  | number
+  | boolean
+  | undefined;
+
+type DeepPartial<T> = T extends Builtin
+  ? T
+  : T extends Array<infer U>
+  ? Array<DeepPartial<U>>
+  : T extends ReadonlyArray<infer U>
+  ? ReadonlyArray<DeepPartial<U>>
+  : T extends {}
+  ? { [K in keyof T]?: DeepPartial<T[K]> }
+  : Partial<T>;
diff --git a/clients/versions/index.d.ts b/clients/versions/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8d3b3896ef7ab787d4f4058e928e750da4f8b056
--- /dev/null
+++ b/clients/versions/index.d.ts
@@ -0,0 +1,3 @@
+export * as content from './content';
+export * as account from './account';
+//# sourceMappingURL=index.d.ts.map
\ No newline at end of file
diff --git a/clients/versions/index.d.ts.map b/clients/versions/index.d.ts.map
new file mode 100644
index 0000000000000000000000000000000000000000..178ed71d3ed660e7c8c2e566cf7145db9f29fc40
--- /dev/null
+++ b/clients/versions/index.d.ts.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,WAAW,CAAA;AACpC,OAAO,KAAK,OAAO,MAAM,WAAW,CAAA"}
\ No newline at end of file
diff --git a/clients/versions/index.js b/clients/versions/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..cd6fe973af10a834c951a0a4a8d30b7360196315
--- /dev/null
+++ b/clients/versions/index.js
@@ -0,0 +1,29 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
+    Object.defineProperty(o, "default", { enumerable: true, value: v });
+}) : function(o, v) {
+    o["default"] = v;
+});
+var __importStar = (this && this.__importStar) || function (mod) {
+    if (mod && mod.__esModule) return mod;
+    var result = {};
+    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
+    __setModuleDefault(result, mod);
+    return result;
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.account = exports.content = void 0;
+exports.content = __importStar(require("./content"));
+exports.account = __importStar(require("./account"));
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/clients/versions/index.js.map b/clients/versions/index.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..bf5d3f3d6d1ab1e0a8203a0b26fb324575c65c8f
--- /dev/null
+++ b/clients/versions/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,qDAAoC;AACpC,qDAAoC"}
\ No newline at end of file