diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..723ef36f4e4f32c4560383aa5987c575a30c6535
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.idea
\ No newline at end of file
diff --git a/README.md b/README.md
index ee6782e7d6909ca86eb0328a22714965520cdc99..4b5a8c6d8b67cd37762c0cb471bd0e664173e9d0 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,3 @@
 # perxis-proto
 
+#### proto-файлы проекта [Perxis](https://git.perx.ru/perxis/perxis)
\ No newline at end of file
diff --git a/proto/clients/clients.proto b/proto/clients/clients.proto
new file mode 100644
index 0000000000000000000000000000000000000000..c20c5d4cab1d94fa740458747c01ac0af52f66eb
--- /dev/null
+++ b/proto/clients/clients.proto
@@ -0,0 +1,125 @@
+syntax = "proto3";
+
+import "google/protobuf/empty.proto";
+
+option go_package = "git.perx.ru/perxis/perxis-go/proto/clients;clients";
+
+package content.clients;
+
+message Client {
+  message OAuth {
+      string client_id = 4;       // Идентификатор клиента выданные IdP сервером, используется для идентификации клиента
+      string auth_id = 5;    // Сервис который используется для авторизации клиента
+      string token_url = 10;      // URL для получения/обновления access token клиента (опционально)
+      string client_secret = 11;    // Секретный Ключ клиента, используется для идентификации клиента (опционально)
+  }
+  message APIKey {
+    string key = 1;
+    bool rotate = 2;
+  }
+  message TLS {
+    string subject = 1;
+  }
+
+  // Внутренний идентификатор клиента внутри системы
+  string id = 1;
+
+  // Идентификатор пространства
+  string space_id = 2;
+
+  // Имя приложения (обязательное поле)
+  string name = 3;
+
+  // Описание клиента, назначение
+  string description = 6;
+
+  // Приложение отключено и не может авторизоваться
+  optional bool disabled = 7;
+
+//  // Приложение имеет доступ к указанным окружениям пространства (ID или Alias)
+//  repeated string environments = 8;
+//
+//  // Список правил доступа к коллекциям
+//  repeated common.Rule rules = 9;
+
+  string role_id = 8;
+
+  OAuth oauth = 10;
+  TLS tls = 11;
+  APIKey api_key = 12;
+}
+
+message CreateRequest {
+  Client client = 1;
+}
+
+message CreateResponse {
+  Client created = 1;
+}
+
+message GetRequest {
+  string space_id = 1;
+  string id = 2;
+}
+
+message GetResponse {
+  Client client = 1;
+}
+
+message GetByRequest {
+  string space_id = 1;
+  string oauth_client_id = 2;
+  string tls_subject= 3;
+  string api_key = 4;
+}
+
+message GetByResponse {
+  Client client = 1;
+}
+
+message UpdateRequest {
+  Client client = 1;
+}
+
+message ListRequest {
+  string space_id = 1;
+}
+
+message ListResponse {
+  repeated Client clients = 1;
+}
+
+message DeleteRequest {
+  string space_id = 1;
+  string id = 2;
+}
+
+message EnableRequest {
+  string space_id = 1;
+  string id = 2;
+  bool enable = 3;
+}
+
+service Clients  {
+
+  // Create - создает клиента (приложение) для работы с API
+  rpc Create(CreateRequest) returns(CreateResponse) {}
+
+  // Get - возвращает клиента по id
+  rpc Get(GetRequest) returns(GetResponse) {}
+
+  // GetByClientID - возвращает клиента по clientId системы авторизации
+  rpc GetBy(GetByRequest) returns(GetByResponse) {}
+
+  // Update - обновляет параметры клиента
+  rpc Update(UpdateRequest) returns(google.protobuf.Empty) {}
+
+  // List - возвращает список клиентов созданных в пространстве
+  rpc List(ListRequest) returns(ListResponse) {}
+
+  // Delete - удаляет указанного клиента из пространстве
+  rpc Delete(DeleteRequest) returns(google.protobuf.Empty) {}
+
+  // Enable - активирует/деактивирует клиента. Клиент не сможет обращаться к API платформы
+  rpc Enable(EnableRequest) returns(google.protobuf.Empty) {}
+}
diff --git a/proto/collaborators/collaborators.proto b/proto/collaborators/collaborators.proto
new file mode 100644
index 0000000000000000000000000000000000000000..263fc8b2058fbde39bc27fcfd1ab844f1c96a822
--- /dev/null
+++ b/proto/collaborators/collaborators.proto
@@ -0,0 +1,52 @@
+syntax = "proto3";
+
+import "google/protobuf/empty.proto";
+import "common/common.proto";
+
+option go_package = "git.perx.ru/perxis/perxis-go/proto/collaborators;collaborators";
+
+package content.collaborators;
+
+message SetRequest {
+  string space_id = 1;
+  string subject = 2;
+  string role = 3;
+}
+
+message GetRequest {
+  string space_id = 1;
+  string subject = 2;
+}
+
+message GetResponse {
+  string role = 3;
+}
+
+message RemoveRequest {
+  string space_id = 1;
+  string subject = 2;
+}
+
+message ListCollaboratorsRequest {
+  string space_id = 1;
+}
+
+message ListCollaboratorsResponse {
+  repeated common.Collaborator collaborators = 1;
+}
+
+message ListSpacesRequest {
+  string subject = 1;
+}
+
+message ListSpacesResponse {
+  repeated common.Collaborator spaces = 1;
+}
+
+service Collaborators {
+  rpc Set(SetRequest) returns(google.protobuf.Empty) {}
+  rpc Get(GetRequest) returns(GetResponse) {}
+  rpc Remove(RemoveRequest) returns(google.protobuf.Empty) {}
+  rpc ListCollaborators(ListCollaboratorsRequest) returns(ListCollaboratorsResponse) {}
+  rpc ListSpaces(ListSpacesRequest) returns(ListSpacesResponse) {}
+}
diff --git a/proto/collections/collections.proto b/proto/collections/collections.proto
new file mode 100644
index 0000000000000000000000000000000000000000..aafd0704118988dbfed484b6720ee271d3230727
--- /dev/null
+++ b/proto/collections/collections.proto
@@ -0,0 +1,119 @@
+syntax = "proto3";
+
+import "google/protobuf/empty.proto";
+import "common/common.proto";
+import "google/protobuf/timestamp.proto";
+
+option go_package = "git.perx.ru/perxis/perxis-go/proto/collections;collections";
+
+package content.collections;
+
+message Access {
+  repeated common.Action actions = 1;
+  repeated string hidden_fields = 5;
+  repeated string readonly_fields = 6;
+  repeated string writeonly_fields = 7;
+}
+
+message Collection {
+  string id = 1;
+  string space_id = 2;
+  string env_id = 3;
+  string name = 4;
+  optional bool single = 5;
+  optional bool system = 6;
+  optional bool no_data = 12;
+  string schema = 7;
+//  string feature = 8;
+  bool hidden = 13;
+
+  message View {
+    string space_id = 1;
+    string env_id = 2;
+    string collection_id  = 3;
+    string filter = 4;
+  }
+  View view = 9;
+
+  enum State {
+    NEW = 0; // коллекция создана, еще не обработана
+    PREPARING = 1; // производится подготовка коллекции (создание индексов, копирование данных)
+    READY = 2; // коллекция готова к работе
+    ERROR = 3; // при обработке коллекции произошла ошибка
+    CHANGED = 4; // в коллекцию внесены изменения, но  еще не были применены. Коллекция должна после перейти в состояние Preparing
+  }
+  message StateInfo {
+    State state = 1;
+    string info = 2;
+    google.protobuf.Timestamp started_at = 3;
+  }
+  StateInfo state_info = 10;
+
+  Access access = 20;
+}
+
+message CreateRequest {
+  Collection collection = 1;
+}
+message CreateResponse {
+  Collection created = 1;
+}
+
+message GetOptions {
+  bool disable_schema_includes = 1;
+}
+
+message GetRequest {
+  string space_id = 1;
+  string env_id = 2;
+  string collection_id = 3;
+  GetOptions options = 4;
+}
+
+message GetResponse {
+  Collection collection = 1;
+}
+
+message ListRequest {
+  message Filter {
+    bool exclude_system = 1;
+   // bool exclude_no_data = 2;
+    bool include_no_data = 5;
+    bool include_hidden = 6;
+    repeated string name = 3;
+    repeated string id = 4;
+  }
+
+  string space_id = 1;
+  string env_id = 2;
+  Filter filter = 5;
+}
+message ListResponse {
+  repeated Collection collections = 1;
+}
+
+message UpdateRequest {
+  Collection collection = 1;
+}
+
+message SetSchemaRequest {
+  string space_id = 1;
+  string env_id = 2;
+  string collection_id = 3;
+  string schema = 4;
+}
+
+message DeleteRequest {
+  string space_id = 1;
+  string env_id = 2;
+  string collection_id = 3;
+}
+
+service Collections  {
+  rpc Create(CreateRequest) returns(CreateResponse) {}
+  rpc Get(GetRequest) returns(GetResponse) {}
+  rpc List(ListRequest) returns(ListResponse) {}
+  rpc Update(UpdateRequest) returns(google.protobuf.Empty) {}
+  rpc SetSchema(SetSchemaRequest) returns(google.protobuf.Empty) {}
+  rpc Delete(DeleteRequest) returns(google.protobuf.Empty) {}
+}
diff --git a/proto/common/common.proto b/proto/common/common.proto
new file mode 100644
index 0000000000000000000000000000000000000000..60a918a78edde0584408543f191e3a8fc4ffded3
--- /dev/null
+++ b/proto/common/common.proto
@@ -0,0 +1,99 @@
+syntax = "proto3";
+
+option go_package = "git.perx.ru/perxis/perxis-go/proto/common;common";
+
+package common;
+
+import "google/protobuf/struct.proto";
+
+message Error {
+  message BadRequest {
+    message FieldViolation {
+      string field = 1;
+      string description = 2;
+    }
+    repeated FieldViolation errors = 1;
+  }
+
+  message Help {
+    message Link {
+      string description =1;
+      string url = 2;
+    }
+    repeated Link links = 1;
+  }
+
+  message DebugInfo {
+    repeated string stack_trace = 1;
+    string detail = 2;
+  }
+
+  message LocalizedMessage {
+    string locale = 1;
+    string message = 2;
+  }
+
+  uint64 error_code = 1; // Код ошибки
+  string error_id = 2; // ID конкретного инцидента, ID уникальна для каждого случая.
+  string reason = 3; // ???
+  string domain = 4; // Сервис,Пакет к которому относится ошибка
+  map<string,string> metadata = 9; // Мета-информация
+  BadRequest bad_request = 10; // Ошибка запроса
+  DebugInfo debug_info = 11; // Отладочная информация
+  Help help = 100; // Пользовательская информации и инструкции
+  repeated LocalizedMessage localized_messages = 200; // Перевод сообщения об ошибке
+}
+
+message Filter {
+  string op = 1;
+  string field = 2;
+  google.protobuf.Value value = 3;
+}
+
+message FindOptions {
+  repeated string sort = 1;
+  int32 page_num = 2;
+  int32 page_size = 3;
+  repeated string fields = 4;
+  bool exclude_fields = 5;
+}
+
+
+enum Access {
+  ANY = 0;
+  MINE = 1;
+  ROLE = 2;
+}
+
+enum Action {
+  UNKNOWN = 0;
+  CREATE = 1;
+  READ = 2;
+  UPDATE = 3;
+  DELETE = 4;
+}
+
+message Rule {
+  string collection_id = 1;
+  repeated Action actions = 2;
+  Access access = 3;
+  repeated string hidden_fields = 5;
+  repeated string readonly_fields = 6;
+  repeated string writeonly_fields = 7;
+  string read_filter = 8;
+  string write_filter = 9;
+}
+
+message Collaborator {
+  string space_id = 1;
+  string subject = 2;
+  string role = 3;
+}
+
+message Version {
+  string server_version = 1;
+  string api_version = 2;
+  string build_time = 3;
+  string commit = 4;
+  int32 build_number = 5;
+}
diff --git a/proto/delivery/delivery.proto b/proto/delivery/delivery.proto
new file mode 100644
index 0000000000000000000000000000000000000000..a3543e61624a8c1b9efef4cc3ba725b0c9c90270
--- /dev/null
+++ b/proto/delivery/delivery.proto
@@ -0,0 +1,88 @@
+syntax = "proto3";
+
+import "locales/locales.proto";
+import "environments/environments.proto";
+import "collections/collections.proto";
+import "items/items.proto";
+
+option go_package = "git.perx.ru/perxis/perxis-go/proto/delivery;delivery";
+
+package delivery;
+
+message ListLocalesRequest {
+  string space_id = 1;
+}
+message ListLocalesResponse {
+  repeated content.locales.Locale locales = 1;
+}
+
+message GetEnvironmentRequest {
+  string space_id = 1;
+  string env_id = 2;
+}
+
+message GetEnvironmentResponse {
+  content.environments.Environment env = 1;
+}
+
+message ListEnvironmentsRequest {
+  string space_id = 1;
+}
+
+message ListEnvironmentsResponse {
+  repeated content.environments.Environment envs = 1;
+}
+
+message GetCollectionRequest {
+  string space_id = 1;
+  string env_id = 2;
+  string collection_id = 3;
+
+}
+message GetCollectionResponse {
+  content.collections.Collection collection = 1;
+}
+
+message ListCollectionsRequest {
+  string space_id = 1;
+  string env_id = 2;
+}
+message ListCollectionsResponse {
+  repeated content.collections.Collection collections = 1;
+}
+
+message GetItemRequest {
+  string space_id = 1;
+  string env_id = 2;
+  string collection_id = 3;
+  string item_id = 5;
+  content.items.GetPublishedOptions options = 6;
+}
+message GetItemResponse {
+  content.items.Item item = 1;
+}
+
+message FindItemsRequest {
+  string space_id = 1;
+  string env_id = 2;
+  string collection_id = 3;
+  content.items.Filter filter = 5;
+  content.items.FindPublishedOptions options = 6;
+}
+message FindItemsResponse{
+  repeated content.items.Item items = 1;
+  int32 total = 2;
+}
+
+service Delivery  {
+  rpc ListLocales(ListLocalesRequest) returns(ListLocalesResponse) {}
+
+  rpc GetEnvironment(GetEnvironmentRequest) returns(GetEnvironmentResponse) {}
+  rpc ListEnvironments(ListEnvironmentsRequest) returns(ListEnvironmentsResponse) {}
+
+  rpc GetCollection(GetCollectionRequest) returns(GetCollectionResponse) {}
+  rpc ListCollections(ListCollectionsRequest) returns(ListCollectionsResponse) {}
+
+  rpc GetItem(GetItemRequest) returns(GetItemResponse) {}
+  rpc FindItems(FindItemsRequest) returns(FindItemsResponse) {}
+}
diff --git a/proto/environments/environments.proto b/proto/environments/environments.proto
new file mode 100644
index 0000000000000000000000000000000000000000..d12caccc84168bf39852697f6b0fe50129708ba2
--- /dev/null
+++ b/proto/environments/environments.proto
@@ -0,0 +1,85 @@
+syntax = "proto3";
+
+import "google/protobuf/empty.proto";
+
+option go_package = "git.perx.ru/perxis/perxis-go/proto/environments;environments";
+
+package content.environments;
+
+message Environment {
+  string id = 1;
+  string space_id = 2;
+  string description = 3;
+  enum State {
+    UNKNOWN = 0;
+    NEW = 1;
+    PREPARING = 2;
+    READY = 3;
+    ERROR = 4;
+  }
+  State state = 4;
+  string state_info = 5;
+  repeated string aliases = 6;
+  Config config = 10;
+}
+
+message Config {
+  string source_id = 1;
+  repeated string features = 2;
+}
+
+message CreateRequest {
+  Environment env = 1;
+}
+
+message CreateResponse {
+  Environment created = 1;
+}
+
+message ListRequest {
+  string space_id = 1;
+}
+
+message ListResponse {
+  repeated Environment envs = 1;
+}
+
+message GetRequest {
+  string space_id = 1;
+  string env_id = 2;
+}
+
+message GetResponse {
+  Environment env = 1;
+}
+
+message UpdateRequest {
+  Environment env = 1;
+}
+
+message SetAliasRequest {
+  string space_id = 1;
+  string env_id = 2;
+  string alias  = 3;
+}
+
+message RemoveAliasRequest {
+  string space_id = 1;
+  string env_id = 2;
+  string alias  = 3;
+}
+
+message DeleteRequest {
+  string space_id = 1;
+  string env_id = 2;
+}
+
+service Environments {
+  rpc Create(CreateRequest) returns(CreateResponse) {}
+  rpc Get(GetRequest) returns(GetResponse) {}
+  rpc List(ListRequest) returns(ListResponse) {}
+  rpc Update(UpdateRequest) returns(google.protobuf.Empty) {}
+  rpc SetAlias(SetAliasRequest) returns(google.protobuf.Empty) {}
+  rpc RemoveAlias(RemoveAliasRequest) returns(google.protobuf.Empty) {}
+  rpc Delete(DeleteRequest) returns(google.protobuf.Empty) {}
+}
\ No newline at end of file
diff --git a/proto/extensions/extension.proto b/proto/extensions/extension.proto
new file mode 100644
index 0000000000000000000000000000000000000000..fa91d9ef45fd72d048fc23ed20881bfbf6dd7d2a
--- /dev/null
+++ b/proto/extensions/extension.proto
@@ -0,0 +1,224 @@
+/**
+# Расширения (Extensions)
+
+Расширения представляют собой отдельные сервисы предоставляющие дополнительные возможности для пользователей. Сервис
+может предоставлять несколько расширений одновременно.
+
+Для координации взаимодействия используется сервис менеджер расширений (Extension Manager). Для предоставления своих функций в систему сервис должен
+зарегистрироваться на контроллере.
+
+*/
+syntax = "proto3";
+
+option go_package = "git.perx.ru/perxis/perxis-go/proto/extensions;extensions";
+
+package extensions;
+
+import "references/references.proto";
+
+// Extension - API расширения
+service Extension {
+
+  // Для установки расширения выполняется запрос к сервису с указанием расширений которые должны быть установлены. Если
+  // расширение уже установлено процесс возвращает ошибку.
+  rpc Install(InstallRequest) returns (InstallResponse) {}
+
+  // Можно запросить проверку статуса установки для расширения. При этом расширение проверяет наличие необходимых данных в
+  // пространстве или наличие новой версии расширения и сообщает об этом. Никаких действий с данными пространства не
+  // производится.
+  rpc Check(CheckRequest) returns (CheckResponse) {}
+
+  // Сервис выполняет необходимые действия с данными и миграции для соответствия нужной версии расширения.
+  // Если расширение не установлено процесс обновления возвращает ошибку.
+  rpc Update(UpdateRequest) returns (UpdateResponse) {}
+
+  // Удаление расширения из пространства.
+  rpc Uninstall(UninstallRequest) returns (UninstallResponse) {} // Удаление расширений
+
+
+  // Пользовательские Действия (Actions)
+  //
+  // Пользовательские действия позволяют расширить функционал пользовательского интерфейса путем
+  // добавления в интерфейс элементов взаимодействуя с которыми пользователь может вызывать реакцию на
+  // сервере или переход в интерфейсе.
+  //
+  // Пользовательские действия добавляются при установке расширений в системную коллекции `System/Actions`.
+  // Коллекция создается автоматически менеджером расширений. При установке так же отображается меню `Действия`
+  // доступное для всех пользователей.
+  //
+  // Примеры пользовательских действий:
+  // - "Собрать сайт" - добавляется Perxis.Web для сборки сайта, доступна пользователю через меню,
+  //   параметры space_id, env_id. При вызове выполняется запрос на сервер ProcessAction.
+  // - "Посмотреть задачи" - добавляется Tasks для перехода на коллекцию задач. Отображается в меню,
+  //   параметры space_id, env_id.
+  //
+  // Приложения так же могут использовать действия для вызова обработки в других приложениях при
+  // необходимости.
+  rpc Action(ActionRequest) returns(ActionResponse) {} // Выполнить указанное действие
+}
+
+message InstallRequest {
+  repeated string extensions = 10000; // Список расширений для установки
+  string space_id = 10010; // Пространство для установки расширений
+  string env_id = 10020; // Идентификатор окружения для установки (по умолчанию master)
+  bool force = 10100; // Игнорировать и автоматически исправлять ошибки установки
+}
+
+message ExtensionRequestResult {
+  enum State {
+    OK = 0; // Запрос завершен
+    ERROR = 1; // Возникла ошибка
+    PENDING = 2; // Запрос ожидает выполнения
+    IN_PROGRESS = 3; // Запрос выполняется
+  }
+
+  State state = 10000;  // Состояние расширение
+  string extension = 10100; // Имя расширения
+  string msg = 10200; // Сообщение
+  string error = 10300; // Ошибка (state == ERROR)
+  bool update_available = 10400; // Доступно обновление
+}
+
+message InstallResponse {
+  repeated ExtensionRequestResult results = 10000; // Список состояний расширений после установки
+}
+
+message UninstallRequest {
+  repeated string extensions = 10000; // Список расширений для удаления
+  string space_id = 10010; // Пространство для удаления расширений
+  string env_id = 10020; // Идентификатор окружения для установки (по умолчанию master)
+  bool remove = 10100; // Удалить все коллекции и данные
+  bool force = 10200; // Удалять расширения вне зависимости от возможных ошибок, без учета зависимостей
+}
+
+message UninstallResponse {
+  repeated ExtensionRequestResult results = 10000; // Список состояний расширений после удаления
+}
+
+message UpdateRequest {
+  repeated string extensions = 10000; // Список расширений для удаления
+  string space_id = 10010; // Пространство для удаления расширений
+  string env_id = 10020; // Идентификатор окружения для установки (по умолчанию master)
+  bool force = 10100; // Выполнять обновление и автоматически исправлять ошибки
+}
+
+message UpdateResponse {
+  repeated ExtensionRequestResult results = 10000; // Список состояний расширений после удаления
+}
+
+message CheckRequest {
+  repeated string extensions = 10000; // Список расширений для удаления
+  string space_id = 10010; // Пространство для удаления расширений
+  string env_id = 10020; // Идентификатор окружения для установки (по умолчанию master)
+}
+
+message CheckResponse {
+  repeated ExtensionRequestResult results = 10000; // Список состояний расширений
+}
+
+// ActionRequest - запрос на выполнение действия к расширению (или менеджеру расширений)
+message ActionRequest {
+  string extension = 1000;
+  string action = 10100;
+  string space_id = 10500;
+  string env_id = 10510;
+  string collection_id = 10520;
+  string item_id = 10530;
+  repeated string item_ids = 10540;
+
+  // Поля к которым применимо действие. В случае если действие выполняется из списка записей, содержит перечень
+  // полей которые пользователь выбрал для отображения в интерфейсе.
+  repeated string fields = 10550;
+
+  map<string,string> metadata = 11000;
+
+  // Ссылки на записи используемые для выполнения действия (назначение ссылок зависит от действия и расширения)
+  repeated content.references.Reference refs = 11010;
+
+  // Ссылка на документ с параметрами выполнения Action.
+  // Чтобы при выполнении действия открывалась форма параметров, необходимо указать `Action.params_collection`
+  content.references.Reference params = 11020;
+}
+
+message ActionResponse {
+  enum State {
+    DONE = 0; // Запрос завершен
+    ERROR = 1; // Возникла ошибка
+    PENDING = 2; // Запрос ожидает выполнения
+    IN_PROGRESS = 3; // Запрос выполняется
+  }
+
+  State state = 10000;  // Состояние расширение
+  string msg = 10100; // Сообщение о выполнении действия
+  string error = 10200; // Сообщение в случае ошибки
+  repeated Action next = 10300; // Следующие возможные действия. Интерфейс отображает как варианты дальнейших действий пользователя
+  map<string,string>metadata = 10400; // Метаданные запроса
+  repeated content.references.Reference refs = 10320; // Ссылки на записи (назначение ссылок зависит от действия и расширения)
+}
+
+
+/**
+Action описывает как коллекцию в системе с предуставновленными действиями, так и возможные дальнейшие действия после
+получения ответа  (см. `ActionResponse.next`)
+
+Если поле `request` присутствует, но не все требуемые поля заполнены, то значения для них берутся из текущих значений.
+
+Коллекция: space_actions (Пространство/Действия)
+Действия сохраненные в коллекции не содержат поля `request`. Значение заполняется текущими значениями.
+
+Пользовательские действия добавляются при установке расширений или при
+настройке в системную коллекции `Пространство/Действия` (system_actions). Расширения самостоятельно контролирует создание необходимых
+им действий в коллекции.
+
+Интерфейс загружает пользовательские действия и отображает их в интерфейсе соответствующим образом.
+*/
+message Action {
+  // Kind описывает c какой сущность системы связано действие и что требуется передать в качестве параметров
+  // Интерфейс загружает пользовательские действия и отображает их в интерфейсе в зависимости от ActionType.
+  enum Kind {
+    DEFAULT = 0; // Действие не отображается в интерфейсе и могут используется для выполнения дополнительных запросов (см. `ActionResponse.next`) или напрямую из сторонних приложений.
+    SPACE = 1; // Действие связано с пространством (требуется передача space_id). Отображается в меню "Действия".
+    ENVIRONMENT = 2; // Действие связано с окружением (требуется передача space_id, env_id). Отображается в меню "Действия".
+    COLLECTION = 3; // Действие связано с коллекцией (требуется передача space_id, env_id, collection_id). Отображается на экране списка записей.
+    ITEM = 4; // Действие связано с записью (требуется передача space_id, env_id, collection_id, item_id). Отображается на экране редактирования записи.
+    ITEMS = 5; // Действие связано с несколькими записями (требуется передача space_id, env_id, collection_id, item_ids). Отображается на экране списка записей.
+    REVISION = 6; // Действие связано с ревизией записи (требуется передача space_id, env_id, collection_id, item_id, rev_id). На данный момент не используется.
+    CREATE = 7; // Действие создание записи (требуется передача space_id, env_id, collection_id).
+  }
+
+  string extension = 10000; // Расширение
+  string action = 10100; // Идентификатор действия
+  string name = 10200; // Название действия для отображения в интерфейсе (пункт меню, кнопка).
+  string description = 10210; // Описание действия для отображения в интерфейсе
+  string icon = 10220; // Название иконки для отображения действия в интерфейсе
+  content.references.Reference image = 10230; // Изображение для отображения в действия в интерфейсе
+  repeated string groups = 10240; // Группы отображения действия в интерфейсе
+  Kind kind = 10300; // Указывает на что направлено действие
+  repeated string classes = 10310; // Классы данных к которым применимо действие (название коллекций или специальных групп в рамках которых данное действие применимо)
+  // Для `CREATE` действуют следующие правила:
+  // - Для создание записей в коллекции применимы действия которые содержат в classes название коллекции
+  // - Для создания записей в виджетах которые допускают создание записей (Block/BlockList) применимы действия которые содержат:
+  //   - в classes хотя бы одно значение из classes виджета
+  //   - если у виджета не указан classes, тогда названия коллекций которые могут быть использованы для создания элементов в поле (allowed_collections)
+  repeated content.references.Reference refs = 10320; // Ссылки на записи используемые для выполнения действия (назначение ссылок зависит от действия и расширения)
+
+  // Коллекция для сохранения параметрами действия. Если параметр указан, то при выполнении действия будет открываться
+  // форма создания записи в указанной коллекции
+  string params_collection = 10330;
+
+  ActionRequest request = 10400; // Параметры запроса (используется в случае `ActionResponse.next`)
+  bool navigation_action = 10500; // Флаг указывающий что действие переносить пользователя в другую часть интерфейса, а не отправляет запрос на сервер
+
+  // navigation_route - Строка шаблон для перехода в интерфейсе
+  // При указании полного адреса (http(s)://xyz), URL открывается в новом окне браузера
+  // Относительный адрес в пользовательском интерфейсе переносит пользователя в соответствующий раздел без перезагрузки приложения
+  //
+  // Переменные `:var` заменяются на текуще значение в пользовательском интерфейсе (Пример: `/spaces/:spaceId/envs/:envId/cols/:colId`)
+  // Перечень переменных для подстановки:
+  // - :spaceId
+  // - :envId
+  // - :colId
+  // - :itemId
+  //
+  string navigation_route = 10510;
+}
\ No newline at end of file
diff --git a/proto/extensions/manager.proto b/proto/extensions/manager.proto
new file mode 100644
index 0000000000000000000000000000000000000000..0def40164a520bc46acaf6440608a803944bd937
--- /dev/null
+++ b/proto/extensions/manager.proto
@@ -0,0 +1,112 @@
+/**
+
+# Менеджер расширений
+
+Реализует функционал по координации расширений в системе и служит единой точкой доступа для работы с расширениями:
+- Регистрирует все расширения в едином реестре
+- Предоставляет доступ к реестру расширений на получение доступных расширений в системе
+- Контролирует процесс установки расширения, устанавливает все необходимые зависимости в правильном порядке
+- Контролирует создание системной коллекции `system_extensions` (System/Extensions) и создание/удалений в ней установленных расширений
+- Контролирует создание системной коллекции `system_actions` (System/Actions). Выполняет удаление всех действий связанных
+  с расширением при его удалении.
+- Выполняет переадресацию запросов на действия для расширений
+
+Менеджер расширений для контроля установленных расширений использует системные коллекции. При обращении к сервису контента
+используются системный уровень прав для создания необходимых коллекций и получения данных:
+1. `system_extensions` (System Extensions) - доступна только системным пользователям
+2. `system_actions` (System Actions) - по умолчанию доступна только системным пользователям, настройки доступа на чтение
+ выдаются пользователям вручную. В зависимости от пользователя в интерфейсе отображаются те или иные доступные действия.
+
+Проверка наличия коллекций и создание в случае их отсутствия выполняется в момент установки расширений. После установки
+расширения в коллекцию `system_extensions` добавляется запись об установленном расширении. Действия добавляются в
+коллекцию `system_actions` расширениями по собственному усмотрению при установке.
+
+Для обращения к расширениям используются права текущего пользователя запрашивающего операцию. Если пользователь не
+обладает необходимыми правами для выполнения действия то операция вернет ошибку.
+
+*/
+syntax = "proto3";
+
+option go_package = "git.perx.ru/perxis/perxis-go/proto/extensions;extensions";
+
+package extensions;
+
+// ExtensionManager - менеджер расширений. Должен реализовывать так же сервис Extension
+service ExtensionManager {
+  // ##  Регистрация расширений
+  //
+  // Регистрация\Дерегистрация происходить через сервис менеджера расширений (Extension Manager). В процессе регистрации сервис сообщает
+  // о поддерживаемых сервисом действиях (Actions) и версии сервиса и зависимостях:
+  // 1. Действия (Actions) - перечень действия которые обрабатываются сервисом. Включает в себя как системные действия,
+  // так и пользовательские, которые могут быть использованы в интерфейсе;
+  // 2. Имя сервиса/расширения - название сервиса внутри системы;
+  // 3. Версия сервиса - сервис сообщает текущую версию сервиса. Контроллер сообщает пользователю о возможности обновления
+  // расширения при смене версии;
+  // 4. Описание версии - содержит информацию об изменениях в последних версиях расширения;
+  // 5. Зависимости - перечень расширений которые необходимы сервису для функционирования. При установке сервиса
+  // все расширения от которых он зависит, будут так же установлены.
+  rpc RegisterExtensions(RegisterExtensionsRequest) returns (RegisterExtensionsResponse) {}
+
+  rpc UnregisterExtensions(UnregisterExtensionsRequest) returns (UnregisterExtensionsResponse) {}
+
+  // Получить список зарегистрированных сервисов
+  rpc ListExtensions(ListExtensionsRequest) returns (ListExtensionsResponse) {} // Получить список сервисов
+}
+
+// ServiceDescription описание сервиса
+message ExtensionDescriptor {
+  string extension = 10000; // Имя расширения
+  string title = 10010; // Название расширения
+  string description = 10020; // Описание расширения
+  string version = 10100; // Версия расширения
+  string version_description = 10110; // Описание версии
+  repeated string deps = 10200; // Зависимости от других расширений
+  string url = 5; // Адрес для внутри сети, коммуникация между сервисами
+  map<string,string> metadata = 6; // Метаданные сервиса, смотрите документацию по сервису
+//  repeated string actions = 10; // Список обрабатываемых действий. Можно указывать регулярное выражения для фильтрации действий.
+}
+
+message RegisterExtensionsRequest {
+  repeated ExtensionDescriptor extensions = 1;
+}
+
+message RegisterExtensionsResponse {}
+
+message UnregisterExtensionsRequest {
+  repeated ExtensionDescriptor extensions = 1;
+}
+
+message UnregisterExtensionsResponse {}
+
+message ListExtensionsFilter {
+  repeated string extension = 1; // Список имен сервисов для получения результатов. Список может содержать регулярные выражения.
+//  repeated string action = 2; // Список действий обрабатываемых сервисами. Список может содержать регулярные выражения.
+}
+
+message ListExtensionsRequest {
+  ListExtensionsFilter filter = 1;
+}
+
+message ListExtensionsResponse {
+  repeated ExtensionDescriptor extensions = 1;
+}
+
+// Описание коллекций
+
+// space_extensions (Пространство/Расширения)
+
+message SpaceExtensions {
+  enum State {
+    PENDING = 0;
+    INSTALLED = 1;
+    IN_PROGRESS = 2;
+    FAIL = 3;
+  }
+  string extension = 10000;
+  string title = 10010;
+  string version = 10100;
+  repeated string deps = 10200;
+  State state = 10300;
+  string status_error = 10400; // Сообщение к ошибке
+  string status_msg = 10500; // Сообщение к статусу
+}
\ No newline at end of file
diff --git a/proto/files/files.proto b/proto/files/files.proto
new file mode 100644
index 0000000000000000000000000000000000000000..ff3cf8ca7e67a2cf102c901fdbf8900d8cf20ed9
--- /dev/null
+++ b/proto/files/files.proto
@@ -0,0 +1,118 @@
+syntax = "proto3";
+
+import "google/protobuf/empty.proto";
+
+option go_package = "git.perx.ru/perxis/perxis-go/proto/files;files";
+
+package files;
+
+// Сущности
+
+message File {
+  string id = 1;        // Уникальный идентификатор файла в хранилище
+  string name = 2;      // Имя файла
+  int32 size = 3;       // Размер файла
+  string mime_type = 4; // Mime-type файла
+  string url = 5;       // Адрес для загрузки файла
+}
+
+message MultipartUpload {
+  File file = 1;
+  string upload_id = 2;           // Идентификатор загрузки хранилища
+  int32 part_size = 3;           // Размер блока для загрузки
+  repeated string part_urls = 4; // Адреса для загрузки пол
+  repeated CompletedPart parts = 5;  // Идентификаторы загруженных блоков (S3 ETAGs)
+}
+
+message Upload {
+  File file = 1;
+  string upload_url = 2;   // URL для загрузки файлов
+}
+
+message CompletedPart {
+  int32 number = 1;
+  string id = 2;
+}
+
+// Запросы и ответы
+
+message StartUploadRequest {
+  MultipartUpload upload = 1;
+}
+message StartUploadResponse {
+  MultipartUpload upload = 1;
+}
+
+message CompleteUploadRequest {
+  MultipartUpload upload = 1;
+}
+message CompleteUploadResponse {
+  MultipartUpload upload = 1;
+}
+
+message AbortUploadRequest {
+  MultipartUpload upload = 1;
+}
+message AbortUploadResponse {}
+
+message MoveUploadRequest {
+  MultipartUpload upload = 1;
+}
+message MoveUploadResponse {
+  File file = 1;
+}
+
+message UploadRequest {
+  File file = 1;
+}
+message UploadResponse {
+  Upload upload = 1;
+}
+
+message GetFileRequest {
+  string id = 1;
+}
+message GetFileResponse {
+  File file = 1;
+}
+
+message DeleteFileRequest {
+  File file = 1;
+}
+message DeleteFileResponse {}
+
+service Files {
+  // StartUpload - инициирует процедуру загрузки файла в файловое хранилище.
+  // Используется клиентским приложением для начала загрузки файла
+  // Требуемые параметры: объект `MultipartUpload` с вложенным объектом `File`, в котором
+  // обязательные поля  Name и Size.
+  // Возвращает объект с заполненными полями ID, PartSize, PartURLs, MimeType, Size, UploadID.
+  rpc StartUpload(StartUploadRequest) returns(StartUploadResponse) {}
+
+  // CompleteUpload - завершает процедуру загрузку файла
+  // Предполагается, что в объекте, полученном из `StartUpload`, клиент должен заполнить поле
+  // Parts (идентификаторами загруженных блоков (S3 ETAGs)) и передать его в `CompleteUpload`
+  rpc CompleteUpload(CompleteUploadRequest) returns(CompleteUploadResponse) {}
+
+  // AbortUpload - прерывает процедуру загрузки файла, все загруженные части файла удаляются их хранилища
+  rpc AbortUpload(AbortUploadRequest) returns(google.protobuf.Empty) {}
+
+  // MoveUpload - перемещает загруженный файл из временного расположения в постоянное месторасположения.
+  // После перемещение загрузки хранилище выдает новый идентификатор постоянного файла
+  rpc MoveUpload(MoveUploadRequest) returns(MoveUploadResponse) {}
+
+  // Upload - инициация загрузки файла в хранилище. Возвращает объект, содержащий подписанный URL.
+  // Завершение загрузки файла осуществляется выполнением POST-запроса
+  rpc Upload(UploadRequest) returns(UploadResponse) {}
+
+  // GetFile - получить информацию о файле (ссылку) по ID
+  rpc GetFile(GetFileRequest) returns(GetFileResponse) {}
+
+  // DeleteFile - удаляет файл. Если происходит удаление оригинала,
+  // удаляются и все связанные структуры
+  // Возможны следующие ситуации:
+  //  - Удаление оригинального файла. Удаляется файл и все связанные с ним файлы.
+  //  - Удаление связанного файла. Для удаления конкретного файла передается 'ID', 'Type' и 'Name'
+  //  - Удаления связанных файлов конкретного типа (например, все 'thumbnails'). Передается 'ID' и 'Type'
+  rpc DeleteFile(DeleteFileRequest) returns(google.protobuf.Empty) {}
+}
diff --git a/proto/images/images.proto b/proto/images/images.proto
new file mode 100644
index 0000000000000000000000000000000000000000..b58c473680bc45b6f8ed2e0c74adcf1c36f5c96b
--- /dev/null
+++ b/proto/images/images.proto
@@ -0,0 +1,40 @@
+syntax = "proto3";
+
+import "files/files.proto";
+
+option go_package = "git.perx.ru/perxis/perxis-go/proto/images;images";
+
+package images;
+
+message Param {
+  string op = 1;
+  repeated string value = 2;
+}
+
+message GetRequest {
+
+  message GetOptions {
+    repeated Param params = 1;
+  }
+
+  files.File source = 1;
+  GetOptions opts = 2;
+}
+
+message GetResponse {
+  files.File result = 1;
+}
+
+// ImageService - сервис для обработки изображений
+service Images {
+
+  // Get - к файлу, идентификатор которого передан в запросе, применяются параметры.
+  // Может быть передано несколько параметров, порядок учитывается при обработке
+  // Допустимые операции:
+  //  - crop (ширина, высота)
+  //  - fit (ширина, высота)
+  //  - resize (ширина, высота)
+  //  - format (один из форматов [ png, jpeg, jpg, gif ]
+  // Возвращает объект File с заполненным полем File.URL
+  rpc Get(GetRequest) returns(GetResponse) {}
+}
diff --git a/proto/invitations/invitations.proto b/proto/invitations/invitations.proto
new file mode 100644
index 0000000000000000000000000000000000000000..c7be5b0145ceb7dbae9982fcb17335403ba4c665
--- /dev/null
+++ b/proto/invitations/invitations.proto
@@ -0,0 +1,103 @@
+syntax = "proto3";
+
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/wrappers.proto";
+
+option go_package = "git.perx.ru/perxis/perxis-go/proto/invitations;invitations";
+
+package content.invitations;
+
+message Invitation {
+  string id = 1;
+  string email = 2;
+  string org_id = 3;
+  string space_id = 4;
+  string owner_id = 5;
+  string role = 6;
+  google.protobuf.Timestamp created_at = 7;
+  google.protobuf.Timestamp valid_until = 8;
+}
+
+message Filter {
+  repeated string id = 1;
+  repeated string email = 2;
+  repeated string org_id = 3;
+  repeated string space_id = 4;
+  repeated string owner_id = 5;
+  repeated string role = 6;
+}
+
+message FindOptions {
+  repeated string sort = 1;
+  int32 page_num = 2;
+  int32 page_size = 3;
+}
+
+message CreateRequest {
+  Invitation invitation = 1;
+}
+
+message CreateResponse {
+  Invitation invitation = 1;
+}
+
+message GetRequest {
+  string invitation_id = 1;
+}
+
+message GetResponse {
+  Invitation invitation = 1;
+}
+
+message UpdateRequest {
+  string invitation_id = 1;
+  google.protobuf.BoolValue sent = 2; // Флаг отправки приглашения
+  google.protobuf.BoolValue pending = 3; // Флаг принятия приглашения
+  google.protobuf.Timestamp sent_at = 4; // Время отправки приглашения
+  google.protobuf.Timestamp valid_until = 5; // Время до которого приглашение действует
+}
+
+message UpdateInvitationResponse {}
+
+message AcceptRequest {
+  string invitation_id = 1;
+  string user_id = 2;
+}
+
+message AcceptInvitationResponse {}
+
+message FindRequest {
+  Filter filter = 1;
+  FindOptions opts = 2;
+}
+
+message FindResponse {
+  repeated Invitation invitations = 1;
+  int64 total = 2;
+}
+
+message DeleteRequest {
+  string invitation_id = 1;
+}
+
+message DeleteSpaceInvitationResponse {}
+
+service Invitations  {
+  rpc Create(CreateRequest) returns(CreateResponse) {}
+
+  // Получить данные о приглашении
+  rpc Get(GetRequest) returns(GetResponse) {}
+
+  // Обновить данные о приглашении
+  // rpc Update(UpdateRequest) returns(google.protobuf.Empty) {}
+
+  // Принять приглашение
+  rpc Accept(AcceptRequest) returns(google.protobuf.Empty) {}
+
+  // Получить список приглашений для пространства
+  rpc Find(FindRequest) returns(FindResponse) {}
+
+  // Удалить приглашение
+  rpc Delete(DeleteRequest) returns(google.protobuf.Empty) {}
+}
diff --git a/proto/items/items.proto b/proto/items/items.proto
new file mode 100644
index 0000000000000000000000000000000000000000..190eace6cf9d094d72a185044018b393fdc48ed0
--- /dev/null
+++ b/proto/items/items.proto
@@ -0,0 +1,304 @@
+/**
+ * # Items
+ *
+ * API Сервиса работы с пользовательским записями (Items)
+ *
+ * Предоставляет доступ к записям пользовательских коллекций
+ *
+ */
+syntax = "proto3";
+
+import "google/protobuf/empty.proto";
+import "common/common.proto";
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/struct.proto";
+
+option go_package = "git.perx.ru/perxis/perxis-go/proto/items;items";
+
+package content.items;
+
+message Error {
+	string message = 1; // Сообщение об ошибке
+	string field = 2; // Поле в котором произошла ошибка
+
+}
+
+message DecodeError {
+  repeated Error errors = 2;
+}
+
+message ValidationError {
+  repeated Error errors = 2;
+}
+
+message ModificationError {
+  repeated Error errors = 2;
+}
+
+message Permissions {
+  bool edit = 1;
+  bool archive = 2;
+  bool publish = 3;
+  bool soft_delete = 4;
+  bool hard_delete = 5;
+}
+
+/**
+ * Пользовательская запись
+ */
+message Item {
+  enum State {
+    DRAFT = 0;
+    PUBLISHED = 1;
+    CHANGED = 2;
+    ARCHIVED = 3;
+  }
+  string id = 1;
+  string space_id = 2;
+  string env_id = 3;
+  string collection_id = 4;
+  State state = 5;
+  google.protobuf.Timestamp created_rev_at = 6; // дата создания текущей ревизии
+  string created_by = 7;                        // id пользователя создавшего первую ревизию
+  google.protobuf.Timestamp created_at = 8;     // дата создания первой ревизии
+  string updated_by = 9;                       // id пользователя обновившего текущую ревизию
+  google.protobuf.Timestamp updated_at = 10;     // дата обновления текущей ревизии
+  google.protobuf.Struct data = 11;
+  map<string, google.protobuf.Struct> translations = 12;
+  string revision_id = 13;
+  google.protobuf.Timestamp published_at = 14;
+  string published_by = 15;
+  google.protobuf.Timestamp archived_at = 16;
+  string archived_by = 17;
+  string locale = 18;
+  bool deleted = 19;
+  bool hidden = 20;
+  bool template = 21;
+  Permissions permissions = 22;
+}
+
+message Filter {
+  repeated string id = 1; // Список ID записей кото
+  repeated common.Filter data = 2; // Список фильтров
+  repeated string q = 3; // Список выражений для фильтрации
+}
+
+message CreateOptions {
+  bool update_attrs = 1;
+}
+
+message FindOptions {
+  common.FindOptions options = 2;
+  bool deleted = 3;
+  bool regular = 4;
+  bool hidden = 5;
+  bool templates = 6;
+}
+
+message UpdateOptions {
+  bool update_attrs = 1;
+}
+
+message GetPublishedOptions {
+  string locale_id = 1;
+}
+
+message DeleteOptions {
+  bool erase = 1;
+}
+
+message PublishOptions {
+  bool update_attrs = 1;
+}
+
+message FindPublishedOptions {
+  common.FindOptions options = 2;
+  string locale_id = 3;
+  bool regular = 4;
+  bool hidden = 5;
+  bool templates = 6;
+}
+
+message FindArchivedOptions {
+  common.FindOptions options = 2;
+}
+
+message ListRevisionsOptions {
+  common.FindOptions options = 2;
+}
+
+message CreateRequest {
+  Item item = 1;
+  CreateOptions options = 2;
+}
+message CreateResponse {
+  Item created = 1;
+}
+
+message IntrospectRequest {
+  Item item = 1;
+}
+message IntrospectResponse {
+  Item item = 1;
+  string schema = 2;
+  repeated common.Error.BadRequest.FieldViolation validation_errors = 3;
+}
+
+message GetRequest {
+  string space_id = 1;
+  string env_id = 2;
+  string collection_id = 3;
+  string item_id = 4;
+}
+message GetResponse {
+  Item item = 1;
+}
+
+message FindRequest {
+  string space_id = 1; // ID Пространства
+  string env_id = 2; // ID окружения
+  string collection_id = 3; // ID коллекции
+  Filter filter = 4;
+  FindOptions options = 5; // Дополнительные параметры поиска
+}
+message FindResponse{
+  repeated Item items = 1;
+  int32 total = 2;
+}
+
+message UpdateRequest {
+  Item item = 1;
+  UpdateOptions options = 2;
+}
+
+message DeleteRequest {
+  string space_id = 1;
+  string env_id = 2;
+  string collection_id = 3;
+  string item_id = 4;
+  DeleteOptions options = 5;
+}
+
+message UndeleteRequest {
+  string space_id = 1;
+  string env_id = 2;
+  string collection_id = 3;
+  string item_id = 4;
+}
+
+message PublishRequest {
+  Item item = 1;
+  PublishOptions options = 2;
+}
+
+message UnpublishRequest {
+  Item item = 1;
+}
+
+message GetPublishedRequest {
+  string space_id = 1;
+  string env_id = 2;
+  string collection_id = 3;
+  string item_id = 5;
+  GetPublishedOptions options = 10;
+}
+message GetPublishedResponse {
+  Item item = 1;
+}
+
+message FindPublishedRequest {
+  string space_id = 1;
+  string env_id = 2;
+  string collection_id = 3;
+  Filter filter = 4;
+  FindPublishedOptions options = 10;
+}
+message FindPublishedResponse{
+  repeated Item items = 1;
+  int32 total = 2;
+}
+
+message GetRevisionRequest {
+  string space_id = 1;
+  string env_id = 2;
+  string collection_id = 3;
+  string item_id = 4;
+  string revision_id = 5;
+}
+message GetRevisionResponse {
+  Item item = 1;
+}
+
+message ListRevisionsRequest {
+  string space_id = 1;
+  string env_id = 2;
+  string collection_id = 3;
+  string item_id = 4;
+  ListRevisionsOptions options = 10;
+}
+message ListRevisionsResponse {
+  repeated Item items = 1;
+}
+
+/**
+ * Запрос на архивирование элемента
+ */
+message ArchiveRequest {
+  Item item = 1; // Элемент для архивации
+}
+
+message UnarchiveRequest {
+  Item item = 1;
+}
+
+message FindArchivedRequest {
+  string space_id = 1;
+  string env_id = 2;
+  string collection_id = 3;
+  Filter filter = 4;
+  FindArchivedOptions options = 6;
+}
+message FindArchivedResponse{
+  repeated Item items = 1;
+  int32 total = 2;
+}
+
+/**
+ * Сервис API элементов
+ */
+service Items {
+  /**
+   * Создать запись
+   */
+  rpc Create(CreateRequest) returns(CreateResponse) {}
+
+  /**
+   * Валидация данных записи
+   */
+  rpc Introspect(IntrospectRequest) returns(IntrospectResponse) {}
+
+  /**
+   * Получение записи по идентификатору
+   */
+  rpc Get(GetRequest) returns(GetResponse) {}
+
+  /**
+   * Поиск по текущим записям
+   */
+  rpc Find(FindRequest) returns(FindResponse) {}
+  rpc Update(UpdateRequest) returns(google.protobuf.Empty) {}
+  rpc Delete(DeleteRequest) returns(google.protobuf.Empty) {}
+  rpc Undelete(UndeleteRequest) returns(google.protobuf.Empty) {}
+
+  rpc Publish(PublishRequest) returns(google.protobuf.Empty) {}
+  rpc Unpublish(UnpublishRequest) returns(google.protobuf.Empty) {}
+  rpc GetPublished(GetPublishedRequest) returns(GetPublishedResponse) {}
+  rpc FindPublished(FindPublishedRequest) returns(FindPublishedResponse) {}
+
+  rpc GetRevision(GetRevisionRequest) returns(GetRevisionResponse) {}
+  rpc ListRevisions(ListRevisionsRequest) returns(ListRevisionsResponse) {}
+
+  rpc Archive(ArchiveRequest) returns(google.protobuf.Empty) {}
+  rpc FindArchived(FindArchivedRequest) returns(FindArchivedResponse) {}
+  rpc Unarchive(UnarchiveRequest) returns(google.protobuf.Empty) {}
+}
diff --git a/proto/locales/locales.proto b/proto/locales/locales.proto
new file mode 100644
index 0000000000000000000000000000000000000000..dd28974ca61552e1211ef67bcc4f4b7437fee158
--- /dev/null
+++ b/proto/locales/locales.proto
@@ -0,0 +1,39 @@
+syntax = "proto3";
+
+import "google/protobuf/empty.proto";
+
+option go_package = "git.perx.ru/perxis/perxis-go/proto/locales;locales";
+
+package content.locales;
+
+message Locale {
+  string id = 1;
+  string space_id = 2;
+  string name = 3;
+}
+
+message CreateRequest {
+  Locale locale = 1;
+}
+
+message CreateResponse {
+  Locale locale = 1;
+}
+
+message ListRequest {
+  string space_id = 1;
+}
+message ListResponse {
+  repeated Locale locales = 1;
+}
+
+message DeleteRequest {
+  string space_id = 1;
+  string locale_id = 2;
+}
+
+service Locales {
+  rpc Create(CreateRequest) returns(CreateResponse) {}
+  rpc List(ListRequest) returns(ListResponse) {}
+  rpc Delete(DeleteRequest) returns(google.protobuf.Empty) {}
+}
\ No newline at end of file
diff --git a/proto/members/members.proto b/proto/members/members.proto
new file mode 100644
index 0000000000000000000000000000000000000000..430691c382ab20d200687a2fd3a6acbebe2634fd
--- /dev/null
+++ b/proto/members/members.proto
@@ -0,0 +1,80 @@
+syntax = "proto3";
+
+import "google/protobuf/empty.proto";
+import "common/common.proto";
+
+option go_package = "git.perx.ru/perxis/perxis-go/proto/members;members";
+
+package account.members;
+
+// Роль пользователя в организации
+enum Role {
+  NOT_MEMBER = 0; // Не является членом команды - значение по умолчанию
+  MEMBER = 1; // Входит в организацию и команды, может получать доступ к Space в соответствии с политикой доступа
+  OWNER = 2; // admin + может приглашать пользователей на роль owner
+  ADMIN = 3; // Входит в организацию, видит все Space, может задавать политики доступа, может приглашать пользователей на роли member, admin
+}
+
+message Member {
+  string org_id = 1;
+  string user_id = 2;
+  Role role = 3;
+}
+
+message SetRequest {
+  string org_id = 1;
+  string user_id = 2;
+  Role role = 3;
+}
+
+message GetRequest {
+  string org_id = 1;
+  string user_id = 2;
+}
+
+message GetResponse {
+  Role role = 3;
+}
+
+message RemoveRequest {
+  string org_id = 1;
+  string user_id = 2;
+}
+
+message ListMembersRequest {
+  string org_id = 1;
+}
+
+message ListMembersResponse {
+  repeated Member members = 1;
+}
+
+message ListOrganizationsRequest {
+  string user_id = 1;
+}
+
+message ListOrganizationsResponse {
+  repeated Member organizations = 1;
+}
+
+service Members {
+  rpc Set(SetRequest) returns(google.protobuf.Empty) {}
+  rpc Get(GetRequest) returns(GetResponse) {}
+  rpc Remove(RemoveRequest) returns(google.protobuf.Empty) {}
+  rpc ListMembers(ListMembersRequest) returns(ListMembersResponse) {}
+  rpc ListOrganizations(ListOrganizationsRequest) returns(ListOrganizationsResponse) {}
+}
+
+// Внутренний сервис (часть имплементации паттерна Observer). Используется для установки
+// членства в организации при принятии приглашения в пространство
+message OnCollaboratorSetRequest {
+  common.Collaborator collaborator = 1;
+}
+
+message OnCollaboratorSetResponse {
+  string delayed_task_id = 1;
+}
+
+service Observer {
+  rpc OnCollaboratorSet(OnCollaboratorSetRequest) returns(OnCollaboratorSetResponse) {}
+}
diff --git a/proto/organizations/organizations.proto b/proto/organizations/organizations.proto
new file mode 100644
index 0000000000000000000000000000000000000000..a8b039983db55915698248e141f402ba8dac53e3
--- /dev/null
+++ b/proto/organizations/organizations.proto
@@ -0,0 +1,66 @@
+syntax = "proto3";
+
+import "google/protobuf/empty.proto";
+import "common/common.proto";
+
+option go_package = "git.perx.ru/perxis/perxis-go/proto/organizations;organizations";
+
+package account.organizations;
+
+// Организация
+message Organization {
+  string id = 1; // Идентификатор организации
+  string name = 2; // Имя организации
+  string description = 3; // Описание организации
+  string logo_url = 5; // URI изображения логотипа
+  optional string owner_id = 6;
+}
+
+// Запросы и ответы
+
+message CreateRequest {
+  Organization org = 1;
+}
+
+message CreateResponse {
+  Organization created = 1;
+}
+
+message GetRequest {
+  string org_id = 1;
+}
+
+message GetResponse {
+  Organization org = 1;
+}
+
+message UpdateRequest {
+  Organization org = 1;
+}
+
+message DeleteRequest {
+  string org_id = 1;
+}
+
+message Filter {
+  repeated string ids = 3;
+  repeated string names = 4;
+}
+
+message FindRequest {
+  Filter filter = 1;
+  common.FindOptions opts = 2;
+}
+
+message FindResponse {
+  repeated Organization orgs = 1;
+  int64 total = 2;
+}
+
+service Organizations {
+  rpc Create(CreateRequest) returns(CreateResponse) {}
+  rpc Get(GetRequest) returns(GetResponse) {}
+  rpc Delete(DeleteRequest) returns(google.protobuf.Empty) {}
+  rpc Find(FindRequest) returns(FindResponse) {}
+  rpc Update(UpdateRequest) returns(google.protobuf.Empty) {}
+}
diff --git a/proto/references/references.proto b/proto/references/references.proto
new file mode 100644
index 0000000000000000000000000000000000000000..a56d45f9ade1cca2f793affd21e75b7e56b5d83c
--- /dev/null
+++ b/proto/references/references.proto
@@ -0,0 +1,30 @@
+syntax = "proto3";
+
+import "items/items.proto";
+
+option go_package = "git.perx.ru/perxis/perxis-go/proto/references;references";
+
+package content.references;
+
+
+message Reference {
+  string id = 1;
+  string collection_id = 2;
+}
+
+message GetRequest {
+  string space_id = 1;
+  string env_id = 2;
+  repeated Reference references = 3;
+}
+
+message GetResponse {
+  repeated items.Item items = 1;
+  repeated Reference notfound = 2;
+}
+
+// References принимает список ссылок на записи и возвращает два списка:
+// список найденных записей и не найденных ссылок
+service References  {
+  rpc Get(GetRequest) returns(GetResponse) {}
+}
diff --git a/proto/roles/roles.proto b/proto/roles/roles.proto
new file mode 100644
index 0000000000000000000000000000000000000000..04ad46b59c187b9b3609b582a3a66e9a7143c513
--- /dev/null
+++ b/proto/roles/roles.proto
@@ -0,0 +1,88 @@
+syntax = "proto3";
+
+import "google/protobuf/empty.proto";
+import "common/common.proto";
+
+option go_package = "git.perx.ru/perxis/perxis-go/proto/roles;roles";
+
+package content.roles;
+
+message Role {
+  // Внутренний идентификатор роли
+  string id = 1;
+
+  // Идентификатор пространства
+  string space_id = 2;
+
+  // Описание роли, назначение
+  string description = 3;
+
+  // Список правил доступа к коллекциям
+  repeated common.Rule rules = 4;
+
+  // Список доступных окружений (ID или Alias)
+  repeated string environments = 5;
+
+  // Разрешить доступ API управления:
+  // - Управление коллекциями
+  // - Управление приложениями
+  // - Управление ролями
+  // - Управление окружениями
+  // - Управление приглашениями
+  // - Управление locales
+  // - Управление участниками
+  bool allow_management = 10;
+}
+
+message CreateRequest {
+  Role role = 1;
+}
+
+message CreateResponse {
+  Role created = 1;
+}
+
+message GetRequest {
+  string space_id = 1;
+  string role_id = 2;
+}
+
+message GetResponse {
+  Role role = 1;
+}
+
+message UpdateRequest {
+  Role role = 1;
+}
+
+message ListRequest {
+  string space_id = 1;
+}
+
+message ListResponse {
+  repeated Role roles = 1;
+}
+
+message DeleteRequest {
+  string space_id = 1;
+  string role_id = 2;
+}
+
+service Roles  {
+
+  // Create - создает роль в рамках пространства
+  rpc Create(CreateRequest) returns(CreateResponse) {}
+
+  // Get - возвращает роль по id
+  rpc Get(GetRequest) returns(GetResponse) {}
+
+  // Update - обновляет параметры роли
+  rpc Update(UpdateRequest) returns(google.protobuf.Empty) {}
+
+  // List - возвращает список ролей, созданных в пространстве
+  rpc List(ListRequest) returns(ListResponse) {}
+
+  // Delete - удаляет указанную роль из пространстве
+  rpc Delete(DeleteRequest) returns(google.protobuf.Empty) {}
+
+}
\ No newline at end of file
diff --git a/proto/spaces/spaces.proto b/proto/spaces/spaces.proto
new file mode 100644
index 0000000000000000000000000000000000000000..87cbef95d35660369ba9b08f8d3ed858c4080ff6
--- /dev/null
+++ b/proto/spaces/spaces.proto
@@ -0,0 +1,77 @@
+syntax = "proto3";
+
+option go_package = "git.perx.ru/perxis/perxis-go/proto/spaces;spaces";
+
+package content.spaces;
+
+import "google/protobuf/empty.proto";
+
+message Space {
+  string id = 1;
+  string org_id = 2;
+  string name = 3;
+  string description = 4;
+  State state = 5;
+  Config config = 10;
+}
+
+enum State {
+  UNKNOWN = 0;
+  NEW = 1;
+  READY = 2;
+  PREPARING = 3;
+  MAINTENANCE = 4;
+  MIGRATION = 5;
+  DELETING = 6;
+  ERROR = 7;
+}
+
+message Config {
+  repeated string features = 1;
+}
+
+message CreateRequest {
+  Space space = 1;
+}
+
+message CreateResponse {
+  Space created = 1;
+}
+
+message GetRequest {
+  string space_id = 1;
+}
+
+message GetResponse {
+  Space space = 1;
+}
+
+message ListRequest {
+  string org_id = 1;
+}
+
+message ListResponse {
+  repeated Space spaces = 1;
+}
+
+message UpdateRequest {
+  Space space = 1;
+}
+
+message UpdateConfigRequest {
+  string space_id = 1;
+  Config config = 2;
+}
+
+message DeleteRequest {
+  string space_id = 1;
+}
+
+service Spaces {
+  rpc Create(CreateRequest) returns(CreateResponse) {}
+  rpc Get(GetRequest) returns(GetResponse) {}
+  rpc List(ListRequest) returns(ListResponse) {}
+  rpc Update(UpdateRequest) returns(google.protobuf.Empty) {}
+  rpc UpdateConfig(UpdateConfigRequest) returns(google.protobuf.Empty) {}
+  rpc Delete(DeleteRequest) returns(google.protobuf.Empty) {}
+}
diff --git a/proto/status/status.proto b/proto/status/status.proto
new file mode 100644
index 0000000000000000000000000000000000000000..8fca6ab22d9e418c3f09d365d1e70ee8030f301e
--- /dev/null
+++ b/proto/status/status.proto
@@ -0,0 +1,90 @@
+// Copyright (c) 2015, Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+package google.rpc;
+
+import "google/protobuf/any.proto";
+
+option java_multiple_files = true;
+option java_outer_classname = "StatusProto";
+option java_package = "com.google.rpc";
+
+
+// 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.
+message Status {
+  // The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].
+  int32 code = 1;
+
+  // 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.
+  string message = 2;
+
+  // A list of messages that carry the error details.  There will be a
+  // common set of message types for APIs to use.
+  repeated google.protobuf.Any details = 3;
+}
diff --git a/proto/users/users.proto b/proto/users/users.proto
new file mode 100644
index 0000000000000000000000000000000000000000..94b7543231d5f5c43acf86862e5ca9b8bb67a367
--- /dev/null
+++ b/proto/users/users.proto
@@ -0,0 +1,98 @@
+syntax = "proto3";
+
+import "google/protobuf/empty.proto";
+import "google/protobuf/wrappers.proto";
+import "common/common.proto";
+
+option go_package = "git.perx.ru/perxis/perxis-go/proto/users;users";
+
+package account.users;
+
+message User {
+  string id = 1; // Уникальный идентификатор, присваивается системой
+  string name = 2; // Уникальное имя, login
+  repeated string identities = 3; // Authorization subjects (JWT sub claims)
+  string display_name = 4; // Имя пользователя для отображения
+  string email = 5; // Email, указывается пользователем
+  google.protobuf.BoolValue email_verified = 6; // Флаг что email проверен
+  string avatar_url = 7; // URI изображения пользователя
+  google.protobuf.BoolValue system = 10; // Системный пользователь (может получать доступ к расширенному API)
+}
+
+message Filter {
+  repeated string id = 1;
+  repeated string name = 2;
+  repeated string identities = 3;
+  repeated string display_name = 4;
+  repeated string email = 5;
+  google.protobuf.BoolValue email_verified = 6;
+  google.protobuf.BoolValue system = 10;
+}
+
+message CreateRequest {
+  User create = 1;
+}
+
+message CreateResponse {
+  User user = 1;
+}
+
+// userId = `current` для получения текущего пользователя
+message GetRequest {
+  string user_id = 1;
+}
+
+message GetResponse {
+  User user = 1;
+}
+
+message FindRequest {
+  Filter filter = 1;
+  common.FindOptions options = 10;
+}
+
+message FindResponse {
+  repeated User users = 1;
+  int64 total = 2;
+}
+
+// userId = `current` для обновления текущего пользователя
+message UpdateRequest {
+  User update = 2; // Содержит только поля необходимые для обновления
+}
+
+message DeleteRequest {
+  string user_id = 1;
+}
+
+message GetByIdentityRequest {
+  string identity = 1;
+}
+
+message GetByIdentityResponse {
+  User user = 1;
+}
+
+service Users  {
+  // Создание пользователя или регистрация текущего пользователя в системе, если create.id == `current`
+  rpc Create(CreateRequest) returns(CreateResponse) {}
+
+  //  - Получение любого пользователя по идентификатору
+  //  - Получение текущего (от лица которого делается запрос) пользователя по специальному идентификатору `current`
+  rpc Get(GetRequest) returns(GetResponse) {}
+
+  // Найти пользователей с фильтрацией. Фильтры доступны пользователям в зависимости от их прав
+  rpc Find(FindRequest) returns(FindResponse) {}
+
+  //  - Обновление существующего пользователя по идентификатору
+  //  - Обновление текущего пользователя по спец. идентификатору `current`
+  rpc Update(UpdateRequest) returns(google.protobuf.Empty) {}
+
+  //  - Удаление существующего пользователя по идентификатору
+  //  - Удаление текущего пользователя по спец. идентификатору `current`
+  rpc Delete(DeleteRequest) returns(google.protobuf.Empty) {}
+
+  // Метод для внутреннего использования. Недоступен для внешних
+  // запросов - авторизация вернет ошибку `access denied`
+  rpc GetByIdentity(GetByIdentityRequest) returns(GetByIdentityResponse) {}
+}
diff --git a/proto/versions/account/versions.proto b/proto/versions/account/versions.proto
new file mode 100644
index 0000000000000000000000000000000000000000..1018795052b251f3a9467c090ac0262411fefb08
--- /dev/null
+++ b/proto/versions/account/versions.proto
@@ -0,0 +1,16 @@
+syntax = "proto3";
+
+import "google/protobuf/empty.proto";
+import "common/common.proto";
+
+option go_package = "git.perx.ru/perxis/perxis-go/proto/versions/account;account";
+
+package account;
+
+message GetResponse {
+  common.Version version = 1;
+}
+
+service Versions {
+  rpc Get(google.protobuf.Empty) returns(GetResponse) {}
+}
\ No newline at end of file
diff --git a/proto/versions/content/versions.proto b/proto/versions/content/versions.proto
new file mode 100644
index 0000000000000000000000000000000000000000..012eeb1acae3070becda0353653514d704102df1
--- /dev/null
+++ b/proto/versions/content/versions.proto
@@ -0,0 +1,16 @@
+syntax = "proto3";
+
+import "google/protobuf/empty.proto";
+import "common/common.proto";
+
+option go_package = "git.perx.ru/perxis/perxis-go/proto/versions/content;content";
+
+package content;
+
+message GetResponse {
+  common.Version version = 1;
+}
+
+service Versions {
+  rpc Get(google.protobuf.Empty) returns(GetResponse) {}
+}
\ No newline at end of file