diff --git a/build-requirements.txt b/build-requirements.txt
index 75d49c54821f25c01a78441ffc9d93fb26c72958..c4b5cfa486de2791866751702ee88f15801d4bf0 100644
--- a/build-requirements.txt
+++ b/build-requirements.txt
@@ -1,33 +1,37 @@
 appdirs==1.4.4
-build==0.6.1
-certifi==2021.5.30
+backports.entry-points-selectable==1.1.1
+build==0.7.0
+certifi==2021.10.8
 chardet==4.0.0
-check-manifest==0.46
-devpi-client==5.2.2
+charset-normalizer==2.0.9
+check-manifest==0.47
+devpi-client==5.2.3
 devpi-common==3.6.0
-distlib==0.3.2
-filelock==3.0.12
-flake8==3.9.2
-grpcio==1.39.0
-grpcio-tools==1.39.0
-idna==3.2
-importlib-metadata==4.8.1
+distlib==0.3.3
+filelock==3.4.0
+flake8==4.0.1
+grpcio==1.42.0
+grpcio-tools==1.42.0
+idna==3.3
+importlib-metadata==4.8.2
 lazy==1.4
 mccabe==0.6.1
-packaging==21.0
-pep517==0.11.0
-pkginfo==1.7.1
-pluggy==0.13.1
-protobuf==3.17.3
-py==1.10.0
-pycodestyle==2.7.0
-pyflakes==2.3.1
-pyparsing==2.4.7
+packaging==21.3
+pep517==0.12.0
+pkginfo==1.8.2
+platformdirs==2.4.0
+pluggy==1.0.0
+protobuf==3.19.1
+py==1.11.0
+pycodestyle==2.8.0
+pyflakes==2.4.0
+pyparsing==3.0.6
 requests==2.26.0
 six==1.16.0
 toml==0.10.2
-tox==3.24.3
-typing-extensions==3.10.0.2
-urllib3==1.26.6
-virtualenv==20.7.2
-zipp==3.5.0
+tomli==1.2.2
+tox==3.24.4
+typing_extensions==4.0.1
+urllib3==1.26.7
+virtualenv==20.10.0
+zipp==3.6.0
diff --git a/perxis/clients/clients_pb2.py b/perxis/clients/clients_pb2.py
index 13a16a5a1b8ad62e258ad91b9dfcdcc67d7df213..feeee17fdbb010a9ec0da7d11672893e338b8787 100644
--- a/perxis/clients/clients_pb2.py
+++ b/perxis/clients/clients_pb2.py
@@ -21,7 +21,7 @@ DESCRIPTOR = _descriptor.FileDescriptor(
   syntax='proto3',
   serialized_options=b'Z0github.com/perxteam/perxis/proto/clients;clients',
   create_key=_descriptor._internal_create_key,
-  serialized_pb=b'\n\x1cperxis/clients/clients.proto\x12\x0f\x63ontent.clients\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1aperxis/common/common.proto\"\xc4\x01\n\x06\x43lient\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08space_id\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tclient_id\x18\x04 \x01(\t\x12\x0f\n\x07\x61uth_id\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t\x12\x15\n\x08\x64isabled\x18\x07 \x01(\x08H\x00\x88\x01\x01\x12\x14\n\x0c\x65nvironments\x18\x08 \x03(\t\x12\x1b\n\x05rules\x18\t \x03(\x0b\x32\x0c.common.RuleB\x0b\n\t_disabled\"8\n\rCreateRequest\x12\'\n\x06\x63lient\x18\x01 \x01(\x0b\x32\x17.content.clients.Client\":\n\x0e\x43reateResponse\x12(\n\x07\x63reated\x18\x01 \x01(\x0b\x32\x17.content.clients.Client\"*\n\nGetRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\"6\n\x0bGetResponse\x12\'\n\x06\x63lient\x18\x01 \x01(\x0b\x32\x17.content.clients.Client\"L\n\x14GetByClientIDRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x11\n\tclient_id\x18\x02 \x01(\t\x12\x0f\n\x07\x61uth_id\x18\x03 \x01(\t\"@\n\x15GetByClientIDResponse\x12\'\n\x06\x63lient\x18\x01 \x01(\x0b\x32\x17.content.clients.Client\"8\n\rUpdateRequest\x12\'\n\x06\x63lient\x18\x01 \x01(\x0b\x32\x17.content.clients.Client\"\x1f\n\x0bListRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\"8\n\x0cListResponse\x12(\n\x07\x63lients\x18\x01 \x03(\x0b\x32\x17.content.clients.Client\"-\n\rDeleteRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\"=\n\rEnableRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65nable\x18\x03 \x01(\x08\x32\x8f\x04\n\x07\x43lients\x12K\n\x06\x43reate\x12\x1e.content.clients.CreateRequest\x1a\x1f.content.clients.CreateResponse\"\x00\x12\x42\n\x03Get\x12\x1b.content.clients.GetRequest\x1a\x1c.content.clients.GetResponse\"\x00\x12`\n\rGetByClientID\x12%.content.clients.GetByClientIDRequest\x1a&.content.clients.GetByClientIDResponse\"\x00\x12\x42\n\x06Update\x12\x1e.content.clients.UpdateRequest\x1a\x16.google.protobuf.Empty\"\x00\x12\x45\n\x04List\x12\x1c.content.clients.ListRequest\x1a\x1d.content.clients.ListResponse\"\x00\x12\x42\n\x06\x44\x65lete\x12\x1e.content.clients.DeleteRequest\x1a\x16.google.protobuf.Empty\"\x00\x12\x42\n\x06\x45nable\x12\x1e.content.clients.EnableRequest\x1a\x16.google.protobuf.Empty\"\x00\x42\x32Z0github.com/perxteam/perxis/proto/clients;clientsb\x06proto3'
+  serialized_pb=b'\n\x1cperxis/clients/clients.proto\x12\x0f\x63ontent.clients\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1aperxis/common/common.proto\"\xee\x01\n\x06\x43lient\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08space_id\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tclient_id\x18\x04 \x01(\t\x12\x0f\n\x07\x61uth_id\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x06 \x01(\t\x12\x15\n\x08\x64isabled\x18\x07 \x01(\x08H\x00\x88\x01\x01\x12\x14\n\x0c\x65nvironments\x18\x08 \x03(\t\x12\x1b\n\x05rules\x18\t \x03(\x0b\x32\x0c.common.Rule\x12\x11\n\ttoken_url\x18\n \x01(\t\x12\x15\n\rclient_secret\x18\x0b \x01(\tB\x0b\n\t_disabled\"8\n\rCreateRequest\x12\'\n\x06\x63lient\x18\x01 \x01(\x0b\x32\x17.content.clients.Client\":\n\x0e\x43reateResponse\x12(\n\x07\x63reated\x18\x01 \x01(\x0b\x32\x17.content.clients.Client\"*\n\nGetRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\"6\n\x0bGetResponse\x12\'\n\x06\x63lient\x18\x01 \x01(\x0b\x32\x17.content.clients.Client\"L\n\x14GetByClientIDRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x11\n\tclient_id\x18\x02 \x01(\t\x12\x0f\n\x07\x61uth_id\x18\x03 \x01(\t\"@\n\x15GetByClientIDResponse\x12\'\n\x06\x63lient\x18\x01 \x01(\x0b\x32\x17.content.clients.Client\"8\n\rUpdateRequest\x12\'\n\x06\x63lient\x18\x01 \x01(\x0b\x32\x17.content.clients.Client\"\x1f\n\x0bListRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\"8\n\x0cListResponse\x12(\n\x07\x63lients\x18\x01 \x03(\x0b\x32\x17.content.clients.Client\"-\n\rDeleteRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\"=\n\rEnableRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\x0e\n\x06\x65nable\x18\x03 \x01(\x08\x32\x8f\x04\n\x07\x43lients\x12K\n\x06\x43reate\x12\x1e.content.clients.CreateRequest\x1a\x1f.content.clients.CreateResponse\"\x00\x12\x42\n\x03Get\x12\x1b.content.clients.GetRequest\x1a\x1c.content.clients.GetResponse\"\x00\x12`\n\rGetByClientID\x12%.content.clients.GetByClientIDRequest\x1a&.content.clients.GetByClientIDResponse\"\x00\x12\x42\n\x06Update\x12\x1e.content.clients.UpdateRequest\x1a\x16.google.protobuf.Empty\"\x00\x12\x45\n\x04List\x12\x1c.content.clients.ListRequest\x1a\x1d.content.clients.ListResponse\"\x00\x12\x42\n\x06\x44\x65lete\x12\x1e.content.clients.DeleteRequest\x1a\x16.google.protobuf.Empty\"\x00\x12\x42\n\x06\x45nable\x12\x1e.content.clients.EnableRequest\x1a\x16.google.protobuf.Empty\"\x00\x42\x32Z0github.com/perxteam/perxis/proto/clients;clientsb\x06proto3'
   ,
   dependencies=[google_dot_protobuf_dot_empty__pb2.DESCRIPTOR,perxis_dot_common_dot_common__pb2.DESCRIPTOR,])
 
@@ -99,6 +99,20 @@ _CLIENT = _descriptor.Descriptor(
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='token_url', full_name='content.clients.Client.token_url', index=9,
+      number=10, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='client_secret', full_name='content.clients.Client.client_secret', index=10,
+      number=11, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
   ],
   extensions=[
   ],
@@ -117,7 +131,7 @@ _CLIENT = _descriptor.Descriptor(
     fields=[]),
   ],
   serialized_start=107,
-  serialized_end=303,
+  serialized_end=345,
 )
 
 
@@ -148,8 +162,8 @@ _CREATEREQUEST = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=305,
-  serialized_end=361,
+  serialized_start=347,
+  serialized_end=403,
 )
 
 
@@ -180,8 +194,8 @@ _CREATERESPONSE = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=363,
-  serialized_end=421,
+  serialized_start=405,
+  serialized_end=463,
 )
 
 
@@ -219,8 +233,8 @@ _GETREQUEST = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=423,
-  serialized_end=465,
+  serialized_start=465,
+  serialized_end=507,
 )
 
 
@@ -251,8 +265,8 @@ _GETRESPONSE = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=467,
-  serialized_end=521,
+  serialized_start=509,
+  serialized_end=563,
 )
 
 
@@ -297,8 +311,8 @@ _GETBYCLIENTIDREQUEST = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=523,
-  serialized_end=599,
+  serialized_start=565,
+  serialized_end=641,
 )
 
 
@@ -329,8 +343,8 @@ _GETBYCLIENTIDRESPONSE = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=601,
-  serialized_end=665,
+  serialized_start=643,
+  serialized_end=707,
 )
 
 
@@ -361,8 +375,8 @@ _UPDATEREQUEST = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=667,
-  serialized_end=723,
+  serialized_start=709,
+  serialized_end=765,
 )
 
 
@@ -393,8 +407,8 @@ _LISTREQUEST = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=725,
-  serialized_end=756,
+  serialized_start=767,
+  serialized_end=798,
 )
 
 
@@ -425,8 +439,8 @@ _LISTRESPONSE = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=758,
-  serialized_end=814,
+  serialized_start=800,
+  serialized_end=856,
 )
 
 
@@ -464,8 +478,8 @@ _DELETEREQUEST = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=816,
-  serialized_end=861,
+  serialized_start=858,
+  serialized_end=903,
 )
 
 
@@ -510,8 +524,8 @@ _ENABLEREQUEST = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=863,
-  serialized_end=924,
+  serialized_start=905,
+  serialized_end=966,
 )
 
 _CLIENT.fields_by_name['rules'].message_type = perxis_dot_common_dot_common__pb2._RULE
@@ -632,8 +646,8 @@ _CLIENTS = _descriptor.ServiceDescriptor(
   index=0,
   serialized_options=None,
   create_key=_descriptor._internal_create_key,
-  serialized_start=927,
-  serialized_end=1454,
+  serialized_start=969,
+  serialized_end=1496,
   methods=[
   _descriptor.MethodDescriptor(
     name='Create',
diff --git a/perxis/collections/collections_pb2.py b/perxis/collections/collections_pb2.py
index cae262db736bb46caea85151174b3adef0b5ce10..8ac694cba79cd000db3f6ba8f8718f3f683c4cee 100644
--- a/perxis/collections/collections_pb2.py
+++ b/perxis/collections/collections_pb2.py
@@ -13,6 +13,7 @@ _sym_db = _symbol_database.Default()
 
 from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2
 from perxis.common import common_pb2 as perxis_dot_common_dot_common__pb2
+from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2
 
 
 DESCRIPTOR = _descriptor.FileDescriptor(
@@ -21,12 +22,52 @@ DESCRIPTOR = _descriptor.FileDescriptor(
   syntax='proto3',
   serialized_options=b'Z8github.com/perxteam/perxis/proto/collections;collections',
   create_key=_descriptor._internal_create_key,
-  serialized_pb=b'\n$perxis/collections/collections.proto\x12\x13\x63ontent.collections\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1aperxis/common/common.proto\"s\n\x06\x41\x63\x63\x65ss\x12\x1f\n\x07\x61\x63tions\x18\x01 \x03(\x0e\x32\x0e.common.Action\x12\x15\n\rhidden_fields\x18\x05 \x03(\t\x12\x17\n\x0freadonly_fields\x18\x06 \x03(\t\x12\x18\n\x10writeonly_fields\x18\x07 \x03(\t\"\xca\x02\n\nCollection\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08space_id\x18\x02 \x01(\t\x12\x0e\n\x06\x65nv_id\x18\x03 \x01(\t\x12\x0c\n\x04name\x18\x04 \x01(\t\x12\x13\n\x06single\x18\x05 \x01(\x08H\x00\x88\x01\x01\x12\x13\n\x06system\x18\x06 \x01(\x08H\x01\x88\x01\x01\x12\x0e\n\x06schema\x18\x07 \x01(\t\x12\x32\n\x04view\x18\t \x01(\x0b\x32$.content.collections.Collection.View\x12+\n\x06\x61\x63\x63\x65ss\x18\x14 \x01(\x0b\x32\x1b.content.collections.Access\x1aO\n\x04View\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0e\n\x06\x65nv_id\x18\x02 \x01(\t\x12\x15\n\rcollection_id\x18\x03 \x01(\t\x12\x0e\n\x06\x66ilter\x18\x04 \x01(\tB\t\n\x07_singleB\t\n\x07_system\"D\n\rCreateRequest\x12\x33\n\ncollection\x18\x01 \x01(\x0b\x32\x1f.content.collections.Collection\"B\n\x0e\x43reateResponse\x12\x30\n\x07\x63reated\x18\x01 \x01(\x0b\x32\x1f.content.collections.Collection\"E\n\nGetRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0e\n\x06\x65nv_id\x18\x02 \x01(\t\x12\x15\n\rcollection_id\x18\x03 \x01(\t\"B\n\x0bGetResponse\x12\x33\n\ncollection\x18\x01 \x01(\x0b\x32\x1f.content.collections.Collection\"/\n\x0bListRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0e\n\x06\x65nv_id\x18\x02 \x01(\t\"D\n\x0cListResponse\x12\x34\n\x0b\x63ollections\x18\x01 \x03(\x0b\x32\x1f.content.collections.Collection\"D\n\rUpdateRequest\x12\x33\n\ncollection\x18\x01 \x01(\x0b\x32\x1f.content.collections.Collection\"H\n\rDeleteRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0e\n\x06\x65nv_id\x18\x02 \x01(\t\x12\x15\n\rcollection_id\x18\x03 \x01(\t2\x8d\x03\n\x0b\x43ollections\x12S\n\x06\x43reate\x12\".content.collections.CreateRequest\x1a#.content.collections.CreateResponse\"\x00\x12J\n\x03Get\x12\x1f.content.collections.GetRequest\x1a .content.collections.GetResponse\"\x00\x12M\n\x04List\x12 .content.collections.ListRequest\x1a!.content.collections.ListResponse\"\x00\x12\x46\n\x06Update\x12\".content.collections.UpdateRequest\x1a\x16.google.protobuf.Empty\"\x00\x12\x46\n\x06\x44\x65lete\x12\".content.collections.DeleteRequest\x1a\x16.google.protobuf.Empty\"\x00\x42:Z8github.com/perxteam/perxis/proto/collections;collectionsb\x06proto3'
+  serialized_pb=b'\n$perxis/collections/collections.proto\x12\x13\x63ontent.collections\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1aperxis/common/common.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"s\n\x06\x41\x63\x63\x65ss\x12\x1f\n\x07\x61\x63tions\x18\x01 \x03(\x0e\x32\x0e.common.Action\x12\x15\n\rhidden_fields\x18\x05 \x03(\t\x12\x17\n\x0freadonly_fields\x18\x06 \x03(\t\x12\x18\n\x10writeonly_fields\x18\x07 \x03(\t\"\xdf\x04\n\nCollection\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08space_id\x18\x02 \x01(\t\x12\x0e\n\x06\x65nv_id\x18\x03 \x01(\t\x12\x0c\n\x04name\x18\x04 \x01(\t\x12\x13\n\x06single\x18\x05 \x01(\x08H\x00\x88\x01\x01\x12\x13\n\x06system\x18\x06 \x01(\x08H\x01\x88\x01\x01\x12\x0e\n\x06schema\x18\x07 \x01(\t\x12\x0f\n\x07\x66\x65\x61ture\x18\x08 \x01(\t\x12\x32\n\x04view\x18\t \x01(\x0b\x32$.content.collections.Collection.View\x12=\n\nstate_info\x18\n \x01(\x0b\x32).content.collections.Collection.StateInfo\x12+\n\x06\x61\x63\x63\x65ss\x18\x14 \x01(\x0b\x32\x1b.content.collections.Access\x1aO\n\x04View\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0e\n\x06\x65nv_id\x18\x02 \x01(\t\x12\x15\n\rcollection_id\x18\x03 \x01(\t\x12\x0e\n\x06\x66ilter\x18\x04 \x01(\t\x1a\x7f\n\tStateInfo\x12\x34\n\x05state\x18\x01 \x01(\x0e\x32%.content.collections.Collection.State\x12\x0c\n\x04info\x18\x02 \x01(\t\x12.\n\nstarted_at\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"B\n\x05State\x12\x07\n\x03NEW\x10\x00\x12\r\n\tPREPARING\x10\x01\x12\t\n\x05READY\x10\x02\x12\t\n\x05\x45RROR\x10\x03\x12\x0b\n\x07\x43HANGED\x10\x04\x42\t\n\x07_singleB\t\n\x07_system\"D\n\rCreateRequest\x12\x33\n\ncollection\x18\x01 \x01(\x0b\x32\x1f.content.collections.Collection\"B\n\x0e\x43reateResponse\x12\x30\n\x07\x63reated\x18\x01 \x01(\x0b\x32\x1f.content.collections.Collection\"E\n\nGetRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0e\n\x06\x65nv_id\x18\x02 \x01(\t\x12\x15\n\rcollection_id\x18\x03 \x01(\t\"B\n\x0bGetResponse\x12\x33\n\ncollection\x18\x01 \x01(\x0b\x32\x1f.content.collections.Collection\"/\n\x0bListRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0e\n\x06\x65nv_id\x18\x02 \x01(\t\"D\n\x0cListResponse\x12\x34\n\x0b\x63ollections\x18\x01 \x03(\x0b\x32\x1f.content.collections.Collection\"D\n\rUpdateRequest\x12\x33\n\ncollection\x18\x01 \x01(\x0b\x32\x1f.content.collections.Collection\"H\n\rDeleteRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0e\n\x06\x65nv_id\x18\x02 \x01(\t\x12\x15\n\rcollection_id\x18\x03 \x01(\t2\x8d\x03\n\x0b\x43ollections\x12S\n\x06\x43reate\x12\".content.collections.CreateRequest\x1a#.content.collections.CreateResponse\"\x00\x12J\n\x03Get\x12\x1f.content.collections.GetRequest\x1a .content.collections.GetResponse\"\x00\x12M\n\x04List\x12 .content.collections.ListRequest\x1a!.content.collections.ListResponse\"\x00\x12\x46\n\x06Update\x12\".content.collections.UpdateRequest\x1a\x16.google.protobuf.Empty\"\x00\x12\x46\n\x06\x44\x65lete\x12\".content.collections.DeleteRequest\x1a\x16.google.protobuf.Empty\"\x00\x42:Z8github.com/perxteam/perxis/proto/collections;collectionsb\x06proto3'
   ,
-  dependencies=[google_dot_protobuf_dot_empty__pb2.DESCRIPTOR,perxis_dot_common_dot_common__pb2.DESCRIPTOR,])
+  dependencies=[google_dot_protobuf_dot_empty__pb2.DESCRIPTOR,perxis_dot_common_dot_common__pb2.DESCRIPTOR,google_dot_protobuf_dot_timestamp__pb2.DESCRIPTOR,])
 
 
 
+_COLLECTION_STATE = _descriptor.EnumDescriptor(
+  name='State',
+  full_name='content.collections.Collection.State',
+  filename=None,
+  file=DESCRIPTOR,
+  create_key=_descriptor._internal_create_key,
+  values=[
+    _descriptor.EnumValueDescriptor(
+      name='NEW', index=0, number=0,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='PREPARING', index=1, number=1,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='READY', index=2, number=2,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='ERROR', index=3, number=3,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+    _descriptor.EnumValueDescriptor(
+      name='CHANGED', index=4, number=4,
+      serialized_options=None,
+      type=None,
+      create_key=_descriptor._internal_create_key),
+  ],
+  containing_type=None,
+  serialized_options=None,
+  serialized_start=788,
+  serialized_end=854,
+)
+_sym_db.RegisterEnumDescriptor(_COLLECTION_STATE)
+
 
 _ACCESS = _descriptor.Descriptor(
   name='Access',
@@ -76,8 +117,8 @@ _ACCESS = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=118,
-  serialized_end=233,
+  serialized_start=151,
+  serialized_end=266,
 )
 
 
@@ -129,8 +170,53 @@ _COLLECTION_VIEW = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=465,
-  serialized_end=544,
+  serialized_start=578,
+  serialized_end=657,
+)
+
+_COLLECTION_STATEINFO = _descriptor.Descriptor(
+  name='StateInfo',
+  full_name='content.collections.Collection.StateInfo',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='state', full_name='content.collections.Collection.StateInfo.state', index=0,
+      number=1, type=14, cpp_type=8, label=1,
+      has_default_value=False, default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='info', full_name='content.collections.Collection.StateInfo.info', index=1,
+      number=2, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='started_at', full_name='content.collections.Collection.StateInfo.started_at', index=2,
+      number=3, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=659,
+  serialized_end=786,
 )
 
 _COLLECTION = _descriptor.Descriptor(
@@ -191,14 +277,28 @@ _COLLECTION = _descriptor.Descriptor(
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
     _descriptor.FieldDescriptor(
-      name='view', full_name='content.collections.Collection.view', index=7,
+      name='feature', full_name='content.collections.Collection.feature', index=7,
+      number=8, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='view', full_name='content.collections.Collection.view', index=8,
       number=9, type=11, cpp_type=10, label=1,
       has_default_value=False, default_value=None,
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
     _descriptor.FieldDescriptor(
-      name='access', full_name='content.collections.Collection.access', index=8,
+      name='state_info', full_name='content.collections.Collection.state_info', index=9,
+      number=10, type=11, cpp_type=10, label=1,
+      has_default_value=False, default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='access', full_name='content.collections.Collection.access', index=10,
       number=20, type=11, cpp_type=10, label=1,
       has_default_value=False, default_value=None,
       message_type=None, enum_type=None, containing_type=None,
@@ -207,8 +307,9 @@ _COLLECTION = _descriptor.Descriptor(
   ],
   extensions=[
   ],
-  nested_types=[_COLLECTION_VIEW, ],
+  nested_types=[_COLLECTION_VIEW, _COLLECTION_STATEINFO, ],
   enum_types=[
+    _COLLECTION_STATE,
   ],
   serialized_options=None,
   is_extendable=False,
@@ -226,8 +327,8 @@ _COLLECTION = _descriptor.Descriptor(
       create_key=_descriptor._internal_create_key,
     fields=[]),
   ],
-  serialized_start=236,
-  serialized_end=566,
+  serialized_start=269,
+  serialized_end=876,
 )
 
 
@@ -258,8 +359,8 @@ _CREATEREQUEST = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=568,
-  serialized_end=636,
+  serialized_start=878,
+  serialized_end=946,
 )
 
 
@@ -290,8 +391,8 @@ _CREATERESPONSE = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=638,
-  serialized_end=704,
+  serialized_start=948,
+  serialized_end=1014,
 )
 
 
@@ -336,8 +437,8 @@ _GETREQUEST = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=706,
-  serialized_end=775,
+  serialized_start=1016,
+  serialized_end=1085,
 )
 
 
@@ -368,8 +469,8 @@ _GETRESPONSE = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=777,
-  serialized_end=843,
+  serialized_start=1087,
+  serialized_end=1153,
 )
 
 
@@ -407,8 +508,8 @@ _LISTREQUEST = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=845,
-  serialized_end=892,
+  serialized_start=1155,
+  serialized_end=1202,
 )
 
 
@@ -439,8 +540,8 @@ _LISTRESPONSE = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=894,
-  serialized_end=962,
+  serialized_start=1204,
+  serialized_end=1272,
 )
 
 
@@ -471,8 +572,8 @@ _UPDATEREQUEST = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=964,
-  serialized_end=1032,
+  serialized_start=1274,
+  serialized_end=1342,
 )
 
 
@@ -517,14 +618,19 @@ _DELETEREQUEST = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=1034,
-  serialized_end=1106,
+  serialized_start=1344,
+  serialized_end=1416,
 )
 
 _ACCESS.fields_by_name['actions'].enum_type = perxis_dot_common_dot_common__pb2._ACTION
 _COLLECTION_VIEW.containing_type = _COLLECTION
+_COLLECTION_STATEINFO.fields_by_name['state'].enum_type = _COLLECTION_STATE
+_COLLECTION_STATEINFO.fields_by_name['started_at'].message_type = google_dot_protobuf_dot_timestamp__pb2._TIMESTAMP
+_COLLECTION_STATEINFO.containing_type = _COLLECTION
 _COLLECTION.fields_by_name['view'].message_type = _COLLECTION_VIEW
+_COLLECTION.fields_by_name['state_info'].message_type = _COLLECTION_STATEINFO
 _COLLECTION.fields_by_name['access'].message_type = _ACCESS
+_COLLECTION_STATE.containing_type = _COLLECTION
 _COLLECTION.oneofs_by_name['_single'].fields.append(
   _COLLECTION.fields_by_name['single'])
 _COLLECTION.fields_by_name['single'].containing_oneof = _COLLECTION.oneofs_by_name['_single']
@@ -563,12 +669,20 @@ Collection = _reflection.GeneratedProtocolMessageType('Collection', (_message.Me
     # @@protoc_insertion_point(class_scope:content.collections.Collection.View)
     })
   ,
+
+  'StateInfo' : _reflection.GeneratedProtocolMessageType('StateInfo', (_message.Message,), {
+    'DESCRIPTOR' : _COLLECTION_STATEINFO,
+    '__module__' : 'perxis.collections.collections_pb2'
+    # @@protoc_insertion_point(class_scope:content.collections.Collection.StateInfo)
+    })
+  ,
   'DESCRIPTOR' : _COLLECTION,
   '__module__' : 'perxis.collections.collections_pb2'
   # @@protoc_insertion_point(class_scope:content.collections.Collection)
   })
 _sym_db.RegisterMessage(Collection)
 _sym_db.RegisterMessage(Collection.View)
+_sym_db.RegisterMessage(Collection.StateInfo)
 
 CreateRequest = _reflection.GeneratedProtocolMessageType('CreateRequest', (_message.Message,), {
   'DESCRIPTOR' : _CREATEREQUEST,
@@ -636,8 +750,8 @@ _COLLECTIONS = _descriptor.ServiceDescriptor(
   index=0,
   serialized_options=None,
   create_key=_descriptor._internal_create_key,
-  serialized_start=1109,
-  serialized_end=1506,
+  serialized_start=1419,
+  serialized_end=1816,
   methods=[
   _descriptor.MethodDescriptor(
     name='Create',
diff --git a/perxis/common/common_pb2.py b/perxis/common/common_pb2.py
index 844936547905c064a273f58265ee707bf22094b6..fc7c2fec57f356a19d3f8e68f574c54c35e7a96d 100644
--- a/perxis/common/common_pb2.py
+++ b/perxis/common/common_pb2.py
@@ -21,7 +21,7 @@ DESCRIPTOR = _descriptor.FileDescriptor(
   syntax='proto3',
   serialized_options=b'Z.github.com/perxteam/perxis/proto/common;common',
   create_key=_descriptor._internal_create_key,
-  serialized_pb=b'\n\x1aperxis/common/common.proto\x12\x06\x63ommon\x1a\x1cgoogle/protobuf/struct.proto\"\xa6\x05\n\x05\x45rror\x12\x12\n\nerror_code\x18\x01 \x01(\x04\x12\x10\n\x08\x65rror_id\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x0e\n\x06\x64omain\x18\x04 \x01(\t\x12-\n\x08metadata\x18\t \x03(\x0b\x32\x1b.common.Error.MetadataEntry\x12-\n\x0b\x62\x61\x64_request\x18\n \x01(\x0b\x32\x18.common.Error.BadRequest\x12+\n\ndebug_info\x18\x0b \x01(\x0b\x32\x17.common.Error.DebugInfo\x12 \n\x04help\x18\x64 \x01(\x0b\x32\x12.common.Error.Help\x12;\n\x12localized_messages\x18\xc8\x01 \x03(\x0b\x32\x1e.common.Error.LocalizedMessage\x1a{\n\nBadRequest\x12\x37\n\x06\x65rrors\x18\x01 \x03(\x0b\x32\'.common.Error.BadRequest.FieldViolation\x1a\x34\n\x0e\x46ieldViolation\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x1aX\n\x04Help\x12&\n\x05links\x18\x01 \x03(\x0b\x32\x17.common.Error.Help.Link\x1a(\n\x04Link\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x0b\n\x03url\x18\x02 \x01(\t\x1a\x30\n\tDebugInfo\x12\x13\n\x0bstack_trace\x18\x01 \x03(\t\x12\x0e\n\x06\x64\x65tail\x18\x02 \x01(\t\x1a\x33\n\x10LocalizedMessage\x12\x0e\n\x06locale\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"J\n\x06\x46ilter\x12\n\n\x02op\x18\x01 \x01(\t\x12\r\n\x05\x66ield\x18\x02 \x01(\t\x12%\n\x05value\x18\x03 \x01(\x0b\x32\x16.google.protobuf.Value\"@\n\x0b\x46indOptions\x12\x0c\n\x04sort\x18\x01 \x03(\t\x12\x10\n\x08page_num\x18\x02 \x01(\x05\x12\x11\n\tpage_size\x18\x03 \x01(\x05\"\xb8\x01\n\x04Rule\x12\x15\n\rcollection_id\x18\x01 \x01(\t\x12\x1f\n\x07\x61\x63tions\x18\x02 \x03(\x0e\x32\x0e.common.Action\x12\x1e\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\x0e\x32\x0e.common.Access\x12\x15\n\rhidden_fields\x18\x05 \x03(\t\x12\x17\n\x0freadonly_fields\x18\x06 \x03(\t\x12\x18\n\x10writeonly_fields\x18\x07 \x03(\t\x12\x0e\n\x06\x66ilter\x18\x08 \x01(\t\"?\n\x0c\x43ollaborator\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0f\n\x07user_id\x18\x02 \x01(\t\x12\x0c\n\x04role\x18\x03 \x01(\t\"p\n\x07Version\x12\x16\n\x0eserver_version\x18\x01 \x01(\t\x12\x13\n\x0b\x61pi_version\x18\x02 \x01(\t\x12\x12\n\nbuild_time\x18\x03 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x04 \x01(\t\x12\x14\n\x0c\x62uild_number\x18\x05 \x01(\x05*%\n\x06\x41\x63\x63\x65ss\x12\x07\n\x03\x41NY\x10\x00\x12\x08\n\x04MINE\x10\x01\x12\x08\n\x04ROLE\x10\x02*C\n\x06\x41\x63tion\x12\x0b\n\x07UNKNOWN\x10\x00\x12\n\n\x06\x43REATE\x10\x01\x12\x08\n\x04READ\x10\x02\x12\n\n\x06UPDATE\x10\x03\x12\n\n\x06\x44\x45LETE\x10\x04\x42\x30Z.github.com/perxteam/perxis/proto/common;commonb\x06proto3'
+  serialized_pb=b'\n\x1aperxis/common/common.proto\x12\x06\x63ommon\x1a\x1cgoogle/protobuf/struct.proto\"\xa6\x05\n\x05\x45rror\x12\x12\n\nerror_code\x18\x01 \x01(\x04\x12\x10\n\x08\x65rror_id\x18\x02 \x01(\t\x12\x0e\n\x06reason\x18\x03 \x01(\t\x12\x0e\n\x06\x64omain\x18\x04 \x01(\t\x12-\n\x08metadata\x18\t \x03(\x0b\x32\x1b.common.Error.MetadataEntry\x12-\n\x0b\x62\x61\x64_request\x18\n \x01(\x0b\x32\x18.common.Error.BadRequest\x12+\n\ndebug_info\x18\x0b \x01(\x0b\x32\x17.common.Error.DebugInfo\x12 \n\x04help\x18\x64 \x01(\x0b\x32\x12.common.Error.Help\x12;\n\x12localized_messages\x18\xc8\x01 \x03(\x0b\x32\x1e.common.Error.LocalizedMessage\x1a{\n\nBadRequest\x12\x37\n\x06\x65rrors\x18\x01 \x03(\x0b\x32\'.common.Error.BadRequest.FieldViolation\x1a\x34\n\x0e\x46ieldViolation\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x1aX\n\x04Help\x12&\n\x05links\x18\x01 \x03(\x0b\x32\x17.common.Error.Help.Link\x1a(\n\x04Link\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x0b\n\x03url\x18\x02 \x01(\t\x1a\x30\n\tDebugInfo\x12\x13\n\x0bstack_trace\x18\x01 \x03(\t\x12\x0e\n\x06\x64\x65tail\x18\x02 \x01(\t\x1a\x33\n\x10LocalizedMessage\x12\x0e\n\x06locale\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"J\n\x06\x46ilter\x12\n\n\x02op\x18\x01 \x01(\t\x12\r\n\x05\x66ield\x18\x02 \x01(\t\x12%\n\x05value\x18\x03 \x01(\x0b\x32\x16.google.protobuf.Value\"@\n\x0b\x46indOptions\x12\x0c\n\x04sort\x18\x01 \x03(\t\x12\x10\n\x08page_num\x18\x02 \x01(\x05\x12\x11\n\tpage_size\x18\x03 \x01(\x05\"\xd3\x01\n\x04Rule\x12\x15\n\rcollection_id\x18\x01 \x01(\t\x12\x1f\n\x07\x61\x63tions\x18\x02 \x03(\x0e\x32\x0e.common.Action\x12\x1e\n\x06\x61\x63\x63\x65ss\x18\x03 \x01(\x0e\x32\x0e.common.Access\x12\x15\n\rhidden_fields\x18\x05 \x03(\t\x12\x17\n\x0freadonly_fields\x18\x06 \x03(\t\x12\x18\n\x10writeonly_fields\x18\x07 \x03(\t\x12\x13\n\x0bread_filter\x18\x08 \x01(\t\x12\x14\n\x0cwrite_filter\x18\t \x01(\t\"?\n\x0c\x43ollaborator\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0f\n\x07user_id\x18\x02 \x01(\t\x12\x0c\n\x04role\x18\x03 \x01(\t\"p\n\x07Version\x12\x16\n\x0eserver_version\x18\x01 \x01(\t\x12\x13\n\x0b\x61pi_version\x18\x02 \x01(\t\x12\x12\n\nbuild_time\x18\x03 \x01(\t\x12\x0e\n\x06\x63ommit\x18\x04 \x01(\t\x12\x14\n\x0c\x62uild_number\x18\x05 \x01(\x05*%\n\x06\x41\x63\x63\x65ss\x12\x07\n\x03\x41NY\x10\x00\x12\x08\n\x04MINE\x10\x01\x12\x08\n\x04ROLE\x10\x02*C\n\x06\x41\x63tion\x12\x0b\n\x07UNKNOWN\x10\x00\x12\n\n\x06\x43REATE\x10\x01\x12\x08\n\x04READ\x10\x02\x12\n\n\x06UPDATE\x10\x03\x12\n\n\x06\x44\x45LETE\x10\x04\x42\x30Z.github.com/perxteam/perxis/proto/common;commonb\x06proto3'
   ,
   dependencies=[google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,])
 
@@ -50,8 +50,8 @@ _ACCESS = _descriptor.EnumDescriptor(
   ],
   containing_type=None,
   serialized_options=None,
-  serialized_start=1257,
-  serialized_end=1294,
+  serialized_start=1284,
+  serialized_end=1321,
 )
 _sym_db.RegisterEnumDescriptor(_ACCESS)
 
@@ -91,8 +91,8 @@ _ACTION = _descriptor.EnumDescriptor(
   ],
   containing_type=None,
   serialized_options=None,
-  serialized_start=1296,
-  serialized_end=1363,
+  serialized_start=1323,
+  serialized_end=1390,
 )
 _sym_db.RegisterEnumDescriptor(_ACTION)
 
@@ -591,12 +591,19 @@ _RULE = _descriptor.Descriptor(
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
     _descriptor.FieldDescriptor(
-      name='filter', full_name='common.Rule.filter', index=6,
+      name='read_filter', full_name='common.Rule.read_filter', index=6,
       number=8, type=9, cpp_type=9, label=1,
       has_default_value=False, default_value=b"".decode('utf-8'),
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='write_filter', full_name='common.Rule.write_filter', index=7,
+      number=9, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
   ],
   extensions=[
   ],
@@ -610,7 +617,7 @@ _RULE = _descriptor.Descriptor(
   oneofs=[
   ],
   serialized_start=892,
-  serialized_end=1076,
+  serialized_end=1103,
 )
 
 
@@ -655,8 +662,8 @@ _COLLABORATOR = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=1078,
-  serialized_end=1141,
+  serialized_start=1105,
+  serialized_end=1168,
 )
 
 
@@ -715,8 +722,8 @@ _VERSION = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=1143,
-  serialized_end=1255,
+  serialized_start=1170,
+  serialized_end=1282,
 )
 
 _ERROR_BADREQUEST_FIELDVIOLATION.containing_type = _ERROR_BADREQUEST
diff --git a/perxis/delivery/delivery_pb2.py b/perxis/delivery/delivery_pb2.py
index 308232e00cf6d465a3c36a37502d2f1923e3adf8..dec91206217ff4430d3de1ffb520ca14c116dc98 100644
--- a/perxis/delivery/delivery_pb2.py
+++ b/perxis/delivery/delivery_pb2.py
@@ -23,7 +23,7 @@ DESCRIPTOR = _descriptor.FileDescriptor(
   syntax='proto3',
   serialized_options=b'Z2github.com/perxteam/perxis/proto/delivery;delivery',
   create_key=_descriptor._internal_create_key,
-  serialized_pb=b'\n\x1eperxis/delivery/delivery.proto\x12\x08\x64\x65livery\x1a\x1cperxis/locales/locales.proto\x1a&perxis/environments/environments.proto\x1a$perxis/collections/collections.proto\x1a\x18perxis/items/items.proto\"&\n\x12ListLocalesRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\"?\n\x13ListLocalesResponse\x12(\n\x07locales\x18\x01 \x03(\x0b\x32\x17.content.locales.Locale\"9\n\x15GetEnvironmentRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0e\n\x06\x65nv_id\x18\x02 \x01(\t\"H\n\x16GetEnvironmentResponse\x12.\n\x03\x65nv\x18\x01 \x01(\x0b\x32!.content.environments.Environment\"+\n\x17ListEnvironmentsRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\"K\n\x18ListEnvironmentsResponse\x12/\n\x04\x65nvs\x18\x01 \x03(\x0b\x32!.content.environments.Environment\"O\n\x14GetCollectionRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0e\n\x06\x65nv_id\x18\x02 \x01(\t\x12\x15\n\rcollection_id\x18\x03 \x01(\t\"L\n\x15GetCollectionResponse\x12\x33\n\ncollection\x18\x01 \x01(\x0b\x32\x1f.content.collections.Collection\":\n\x16ListCollectionsRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0e\n\x06\x65nv_id\x18\x02 \x01(\t\"O\n\x17ListCollectionsResponse\x12\x34\n\x0b\x63ollections\x18\x01 \x03(\x0b\x32\x1f.content.collections.Collection\"\x8f\x01\n\x0eGetItemRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0e\n\x06\x65nv_id\x18\x02 \x01(\t\x12\x15\n\rcollection_id\x18\x03 \x01(\t\x12\x0f\n\x07item_id\x18\x05 \x01(\t\x12\x33\n\x07options\x18\x06 \x01(\x0b\x32\".content.items.GetPublishedOptions\"4\n\x0fGetItemResponse\x12!\n\x04item\x18\x01 \x01(\x0b\x32\x13.content.items.Item\"\xbb\x01\n\x10\x46indItemsRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0e\n\x06\x65nv_id\x18\x02 \x01(\t\x12\x15\n\rcollection_id\x18\x03 \x01(\t\x12\x11\n\tlocale_id\x18\x04 \x01(\t\x12%\n\x06\x66ilter\x18\x05 \x01(\x0b\x32\x15.content.items.Filter\x12\x34\n\x07options\x18\x06 \x01(\x0b\x32#.content.items.FindPublishedOptions\"F\n\x11\x46indItemsResponse\x12\"\n\x05items\x18\x01 \x03(\x0b\x32\x13.content.items.Item\x12\r\n\x05total\x18\x02 \x01(\x05\x32\xc4\x04\n\x08\x44\x65livery\x12L\n\x0bListLocales\x12\x1c.delivery.ListLocalesRequest\x1a\x1d.delivery.ListLocalesResponse\"\x00\x12U\n\x0eGetEnvironment\x12\x1f.delivery.GetEnvironmentRequest\x1a .delivery.GetEnvironmentResponse\"\x00\x12[\n\x10ListEnvironments\x12!.delivery.ListEnvironmentsRequest\x1a\".delivery.ListEnvironmentsResponse\"\x00\x12R\n\rGetCollection\x12\x1e.delivery.GetCollectionRequest\x1a\x1f.delivery.GetCollectionResponse\"\x00\x12X\n\x0fListCollections\x12 .delivery.ListCollectionsRequest\x1a!.delivery.ListCollectionsResponse\"\x00\x12@\n\x07GetItem\x12\x18.delivery.GetItemRequest\x1a\x19.delivery.GetItemResponse\"\x00\x12\x46\n\tFindItems\x12\x1a.delivery.FindItemsRequest\x1a\x1b.delivery.FindItemsResponse\"\x00\x42\x34Z2github.com/perxteam/perxis/proto/delivery;deliveryb\x06proto3'
+  serialized_pb=b'\n\x1eperxis/delivery/delivery.proto\x12\x08\x64\x65livery\x1a\x1cperxis/locales/locales.proto\x1a&perxis/environments/environments.proto\x1a$perxis/collections/collections.proto\x1a\x18perxis/items/items.proto\"&\n\x12ListLocalesRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\"?\n\x13ListLocalesResponse\x12(\n\x07locales\x18\x01 \x03(\x0b\x32\x17.content.locales.Locale\"9\n\x15GetEnvironmentRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0e\n\x06\x65nv_id\x18\x02 \x01(\t\"H\n\x16GetEnvironmentResponse\x12.\n\x03\x65nv\x18\x01 \x01(\x0b\x32!.content.environments.Environment\"+\n\x17ListEnvironmentsRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\"K\n\x18ListEnvironmentsResponse\x12/\n\x04\x65nvs\x18\x01 \x03(\x0b\x32!.content.environments.Environment\"O\n\x14GetCollectionRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0e\n\x06\x65nv_id\x18\x02 \x01(\t\x12\x15\n\rcollection_id\x18\x03 \x01(\t\"L\n\x15GetCollectionResponse\x12\x33\n\ncollection\x18\x01 \x01(\x0b\x32\x1f.content.collections.Collection\":\n\x16ListCollectionsRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0e\n\x06\x65nv_id\x18\x02 \x01(\t\"O\n\x17ListCollectionsResponse\x12\x34\n\x0b\x63ollections\x18\x01 \x03(\x0b\x32\x1f.content.collections.Collection\"\x8f\x01\n\x0eGetItemRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0e\n\x06\x65nv_id\x18\x02 \x01(\t\x12\x15\n\rcollection_id\x18\x03 \x01(\t\x12\x0f\n\x07item_id\x18\x05 \x01(\t\x12\x33\n\x07options\x18\x06 \x01(\x0b\x32\".content.items.GetPublishedOptions\"4\n\x0fGetItemResponse\x12!\n\x04item\x18\x01 \x01(\x0b\x32\x13.content.items.Item\"\xa8\x01\n\x10\x46indItemsRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0e\n\x06\x65nv_id\x18\x02 \x01(\t\x12\x15\n\rcollection_id\x18\x03 \x01(\t\x12%\n\x06\x66ilter\x18\x05 \x01(\x0b\x32\x15.content.items.Filter\x12\x34\n\x07options\x18\x06 \x01(\x0b\x32#.content.items.FindPublishedOptions\"F\n\x11\x46indItemsResponse\x12\"\n\x05items\x18\x01 \x03(\x0b\x32\x13.content.items.Item\x12\r\n\x05total\x18\x02 \x01(\x05\x32\xc4\x04\n\x08\x44\x65livery\x12L\n\x0bListLocales\x12\x1c.delivery.ListLocalesRequest\x1a\x1d.delivery.ListLocalesResponse\"\x00\x12U\n\x0eGetEnvironment\x12\x1f.delivery.GetEnvironmentRequest\x1a .delivery.GetEnvironmentResponse\"\x00\x12[\n\x10ListEnvironments\x12!.delivery.ListEnvironmentsRequest\x1a\".delivery.ListEnvironmentsResponse\"\x00\x12R\n\rGetCollection\x12\x1e.delivery.GetCollectionRequest\x1a\x1f.delivery.GetCollectionResponse\"\x00\x12X\n\x0fListCollections\x12 .delivery.ListCollectionsRequest\x1a!.delivery.ListCollectionsResponse\"\x00\x12@\n\x07GetItem\x12\x18.delivery.GetItemRequest\x1a\x19.delivery.GetItemResponse\"\x00\x12\x46\n\tFindItems\x12\x1a.delivery.FindItemsRequest\x1a\x1b.delivery.FindItemsResponse\"\x00\x42\x34Z2github.com/perxteam/perxis/proto/delivery;deliveryb\x06proto3'
   ,
   dependencies=[perxis_dot_locales_dot_locales__pb2.DESCRIPTOR,perxis_dot_environments_dot_environments__pb2.DESCRIPTOR,perxis_dot_collections_dot_collections__pb2.DESCRIPTOR,perxis_dot_items_dot_items__pb2.DESCRIPTOR,])
 
@@ -500,21 +500,14 @@ _FINDITEMSREQUEST = _descriptor.Descriptor(
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
     _descriptor.FieldDescriptor(
-      name='locale_id', full_name='delivery.FindItemsRequest.locale_id', index=3,
-      number=4, type=9, cpp_type=9, label=1,
-      has_default_value=False, default_value=b"".decode('utf-8'),
-      message_type=None, enum_type=None, containing_type=None,
-      is_extension=False, extension_scope=None,
-      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
-    _descriptor.FieldDescriptor(
-      name='filter', full_name='delivery.FindItemsRequest.filter', index=4,
+      name='filter', full_name='delivery.FindItemsRequest.filter', index=3,
       number=5, type=11, cpp_type=10, label=1,
       has_default_value=False, default_value=None,
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
     _descriptor.FieldDescriptor(
-      name='options', full_name='delivery.FindItemsRequest.options', index=5,
+      name='options', full_name='delivery.FindItemsRequest.options', index=4,
       number=6, type=11, cpp_type=10, label=1,
       has_default_value=False, default_value=None,
       message_type=None, enum_type=None, containing_type=None,
@@ -533,7 +526,7 @@ _FINDITEMSREQUEST = _descriptor.Descriptor(
   oneofs=[
   ],
   serialized_start=1039,
-  serialized_end=1226,
+  serialized_end=1207,
 )
 
 
@@ -571,8 +564,8 @@ _FINDITEMSRESPONSE = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=1228,
-  serialized_end=1298,
+  serialized_start=1209,
+  serialized_end=1279,
 )
 
 _LISTLOCALESRESPONSE.fields_by_name['locales'].message_type = perxis_dot_locales_dot_locales__pb2._LOCALE
@@ -709,8 +702,8 @@ _DELIVERY = _descriptor.ServiceDescriptor(
   index=0,
   serialized_options=None,
   create_key=_descriptor._internal_create_key,
-  serialized_start=1301,
-  serialized_end=1881,
+  serialized_start=1282,
+  serialized_end=1862,
   methods=[
   _descriptor.MethodDescriptor(
     name='ListLocales',
diff --git a/perxis/references/__init__.py b/perxis/references/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/perxis/references/references_pb2.py b/perxis/references/references_pb2.py
new file mode 100644
index 0000000000000000000000000000000000000000..12edbacd40a0a8d389f5a19d7879d051b70c5b9a
--- /dev/null
+++ b/perxis/references/references_pb2.py
@@ -0,0 +1,210 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: perxis/references/references.proto
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from google.protobuf import reflection as _reflection
+from google.protobuf import symbol_database as _symbol_database
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+from perxis.items import items_pb2 as perxis_dot_items_dot_items__pb2
+
+
+DESCRIPTOR = _descriptor.FileDescriptor(
+  name='perxis/references/references.proto',
+  package='content.references',
+  syntax='proto3',
+  serialized_options=b'Z6github.com/perxteam/perxis/proto/references;references',
+  create_key=_descriptor._internal_create_key,
+  serialized_pb=b'\n\"perxis/references/references.proto\x12\x12\x63ontent.references\x1a\x18perxis/items/items.proto\".\n\tReference\x12\n\n\x02id\x18\x01 \x01(\t\x12\x15\n\rcollection_id\x18\x02 \x01(\t\"a\n\nGetRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0e\n\x06\x65nv_id\x18\x02 \x01(\t\x12\x31\n\nreferences\x18\x03 \x03(\x0b\x32\x1d.content.references.Reference\"b\n\x0bGetResponse\x12\"\n\x05items\x18\x01 \x03(\x0b\x32\x13.content.items.Item\x12/\n\x08notfound\x18\x02 \x03(\x0b\x32\x1d.content.references.Reference2V\n\nReferences\x12H\n\x03Get\x12\x1e.content.references.GetRequest\x1a\x1f.content.references.GetResponse\"\x00\x42\x38Z6github.com/perxteam/perxis/proto/references;referencesb\x06proto3'
+  ,
+  dependencies=[perxis_dot_items_dot_items__pb2.DESCRIPTOR,])
+
+
+
+
+_REFERENCE = _descriptor.Descriptor(
+  name='Reference',
+  full_name='content.references.Reference',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='id', full_name='content.references.Reference.id', index=0,
+      number=1, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='collection_id', full_name='content.references.Reference.collection_id', index=1,
+      number=2, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=84,
+  serialized_end=130,
+)
+
+
+_GETREQUEST = _descriptor.Descriptor(
+  name='GetRequest',
+  full_name='content.references.GetRequest',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='space_id', full_name='content.references.GetRequest.space_id', index=0,
+      number=1, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='env_id', full_name='content.references.GetRequest.env_id', index=1,
+      number=2, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=b"".decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='references', full_name='content.references.GetRequest.references', index=2,
+      number=3, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=132,
+  serialized_end=229,
+)
+
+
+_GETRESPONSE = _descriptor.Descriptor(
+  name='GetResponse',
+  full_name='content.references.GetResponse',
+  filename=None,
+  file=DESCRIPTOR,
+  containing_type=None,
+  create_key=_descriptor._internal_create_key,
+  fields=[
+    _descriptor.FieldDescriptor(
+      name='items', full_name='content.references.GetResponse.items', index=0,
+      number=1, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='notfound', full_name='content.references.GetResponse.notfound', index=1,
+      number=2, type=11, cpp_type=10, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+  ],
+  extensions=[
+  ],
+  nested_types=[],
+  enum_types=[
+  ],
+  serialized_options=None,
+  is_extendable=False,
+  syntax='proto3',
+  extension_ranges=[],
+  oneofs=[
+  ],
+  serialized_start=231,
+  serialized_end=329,
+)
+
+_GETREQUEST.fields_by_name['references'].message_type = _REFERENCE
+_GETRESPONSE.fields_by_name['items'].message_type = perxis_dot_items_dot_items__pb2._ITEM
+_GETRESPONSE.fields_by_name['notfound'].message_type = _REFERENCE
+DESCRIPTOR.message_types_by_name['Reference'] = _REFERENCE
+DESCRIPTOR.message_types_by_name['GetRequest'] = _GETREQUEST
+DESCRIPTOR.message_types_by_name['GetResponse'] = _GETRESPONSE
+_sym_db.RegisterFileDescriptor(DESCRIPTOR)
+
+Reference = _reflection.GeneratedProtocolMessageType('Reference', (_message.Message,), {
+  'DESCRIPTOR' : _REFERENCE,
+  '__module__' : 'perxis.references.references_pb2'
+  # @@protoc_insertion_point(class_scope:content.references.Reference)
+  })
+_sym_db.RegisterMessage(Reference)
+
+GetRequest = _reflection.GeneratedProtocolMessageType('GetRequest', (_message.Message,), {
+  'DESCRIPTOR' : _GETREQUEST,
+  '__module__' : 'perxis.references.references_pb2'
+  # @@protoc_insertion_point(class_scope:content.references.GetRequest)
+  })
+_sym_db.RegisterMessage(GetRequest)
+
+GetResponse = _reflection.GeneratedProtocolMessageType('GetResponse', (_message.Message,), {
+  'DESCRIPTOR' : _GETRESPONSE,
+  '__module__' : 'perxis.references.references_pb2'
+  # @@protoc_insertion_point(class_scope:content.references.GetResponse)
+  })
+_sym_db.RegisterMessage(GetResponse)
+
+
+DESCRIPTOR._options = None
+
+_REFERENCES = _descriptor.ServiceDescriptor(
+  name='References',
+  full_name='content.references.References',
+  file=DESCRIPTOR,
+  index=0,
+  serialized_options=None,
+  create_key=_descriptor._internal_create_key,
+  serialized_start=331,
+  serialized_end=417,
+  methods=[
+  _descriptor.MethodDescriptor(
+    name='Get',
+    full_name='content.references.References.Get',
+    index=0,
+    containing_service=None,
+    input_type=_GETREQUEST,
+    output_type=_GETRESPONSE,
+    serialized_options=None,
+    create_key=_descriptor._internal_create_key,
+  ),
+])
+_sym_db.RegisterServiceDescriptor(_REFERENCES)
+
+DESCRIPTOR.services_by_name['References'] = _REFERENCES
+
+# @@protoc_insertion_point(module_scope)
diff --git a/perxis/references/references_pb2_grpc.py b/perxis/references/references_pb2_grpc.py
new file mode 100644
index 0000000000000000000000000000000000000000..89246f3a7d854d7fb104188251f418fc581c2a79
--- /dev/null
+++ b/perxis/references/references_pb2_grpc.py
@@ -0,0 +1,72 @@
+# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
+"""Client and server classes corresponding to protobuf-defined services."""
+import grpc
+
+from perxis.references import references_pb2 as perxis_dot_references_dot_references__pb2
+
+
+class ReferencesStub(object):
+    """References принимает список ссылок на записи и возвращает два списка:
+    список найденных записей и не найденных ссылок
+    """
+
+    def __init__(self, channel):
+        """Constructor.
+
+        Args:
+            channel: A grpc.Channel.
+        """
+        self.Get = channel.unary_unary(
+                '/content.references.References/Get',
+                request_serializer=perxis_dot_references_dot_references__pb2.GetRequest.SerializeToString,
+                response_deserializer=perxis_dot_references_dot_references__pb2.GetResponse.FromString,
+                )
+
+
+class ReferencesServicer(object):
+    """References принимает список ссылок на записи и возвращает два списка:
+    список найденных записей и не найденных ссылок
+    """
+
+    def Get(self, request, context):
+        """Missing associated documentation comment in .proto file."""
+        context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+        context.set_details('Method not implemented!')
+        raise NotImplementedError('Method not implemented!')
+
+
+def add_ReferencesServicer_to_server(servicer, server):
+    rpc_method_handlers = {
+            'Get': grpc.unary_unary_rpc_method_handler(
+                    servicer.Get,
+                    request_deserializer=perxis_dot_references_dot_references__pb2.GetRequest.FromString,
+                    response_serializer=perxis_dot_references_dot_references__pb2.GetResponse.SerializeToString,
+            ),
+    }
+    generic_handler = grpc.method_handlers_generic_handler(
+            'content.references.References', rpc_method_handlers)
+    server.add_generic_rpc_handlers((generic_handler,))
+
+
+ # This class is part of an EXPERIMENTAL API.
+class References(object):
+    """References принимает список ссылок на записи и возвращает два списка:
+    список найденных записей и не найденных ссылок
+    """
+
+    @staticmethod
+    def Get(request,
+            target,
+            options=(),
+            channel_credentials=None,
+            call_credentials=None,
+            insecure=False,
+            compression=None,
+            wait_for_ready=None,
+            timeout=None,
+            metadata=None):
+        return grpc.experimental.unary_unary(request, target, '/content.references.References/Get',
+            perxis_dot_references_dot_references__pb2.GetRequest.SerializeToString,
+            perxis_dot_references_dot_references__pb2.GetResponse.FromString,
+            options, channel_credentials,
+            insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
diff --git a/perxis/roles/roles_pb2.py b/perxis/roles/roles_pb2.py
index 011d293a02647687f7706ae72211822306e32bee..6ae6ad6c498d179dfb2dc83804f337144f5c27c8 100644
--- a/perxis/roles/roles_pb2.py
+++ b/perxis/roles/roles_pb2.py
@@ -21,7 +21,7 @@ DESCRIPTOR = _descriptor.FileDescriptor(
   syntax='proto3',
   serialized_options=b'Z,github.com/perxteam/perxis/proto/roles;roles',
   create_key=_descriptor._internal_create_key,
-  serialized_pb=b'\n\x18perxis/roles/roles.proto\x12\rcontent.roles\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1aperxis/common/common.proto\"V\n\x04Role\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08space_id\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x1b\n\x05rules\x18\x04 \x03(\x0b\x32\x0c.common.Rule\"2\n\rCreateRequest\x12!\n\x04role\x18\x01 \x01(\x0b\x32\x13.content.roles.Role\"6\n\x0e\x43reateResponse\x12$\n\x07\x63reated\x18\x01 \x01(\x0b\x32\x13.content.roles.Role\"/\n\nGetRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0f\n\x07role_id\x18\x02 \x01(\t\"0\n\x0bGetResponse\x12!\n\x04role\x18\x01 \x01(\x0b\x32\x13.content.roles.Role\"2\n\rUpdateRequest\x12!\n\x04role\x18\x01 \x01(\x0b\x32\x13.content.roles.Role\"\x1f\n\x0bListRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\"2\n\x0cListResponse\x12\"\n\x05roles\x18\x01 \x03(\x0b\x32\x13.content.roles.Role\"2\n\rDeleteRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0f\n\x07role_id\x18\x02 \x01(\t2\xd7\x02\n\x05Roles\x12G\n\x06\x43reate\x12\x1c.content.roles.CreateRequest\x1a\x1d.content.roles.CreateResponse\"\x00\x12>\n\x03Get\x12\x19.content.roles.GetRequest\x1a\x1a.content.roles.GetResponse\"\x00\x12@\n\x06Update\x12\x1c.content.roles.UpdateRequest\x1a\x16.google.protobuf.Empty\"\x00\x12\x41\n\x04List\x12\x1a.content.roles.ListRequest\x1a\x1b.content.roles.ListResponse\"\x00\x12@\n\x06\x44\x65lete\x12\x1c.content.roles.DeleteRequest\x1a\x16.google.protobuf.Empty\"\x00\x42.Z,github.com/perxteam/perxis/proto/roles;rolesb\x06proto3'
+  serialized_pb=b'\n\x18perxis/roles/roles.proto\x12\rcontent.roles\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1aperxis/common/common.proto\"l\n\x04Role\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08space_id\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x1b\n\x05rules\x18\x04 \x03(\x0b\x32\x0c.common.Rule\x12\x14\n\x0c\x65nvironments\x18\x05 \x03(\t\"2\n\rCreateRequest\x12!\n\x04role\x18\x01 \x01(\x0b\x32\x13.content.roles.Role\"6\n\x0e\x43reateResponse\x12$\n\x07\x63reated\x18\x01 \x01(\x0b\x32\x13.content.roles.Role\"/\n\nGetRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0f\n\x07role_id\x18\x02 \x01(\t\"0\n\x0bGetResponse\x12!\n\x04role\x18\x01 \x01(\x0b\x32\x13.content.roles.Role\"2\n\rUpdateRequest\x12!\n\x04role\x18\x01 \x01(\x0b\x32\x13.content.roles.Role\"\x1f\n\x0bListRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\"2\n\x0cListResponse\x12\"\n\x05roles\x18\x01 \x03(\x0b\x32\x13.content.roles.Role\"2\n\rDeleteRequest\x12\x10\n\x08space_id\x18\x01 \x01(\t\x12\x0f\n\x07role_id\x18\x02 \x01(\t2\xd7\x02\n\x05Roles\x12G\n\x06\x43reate\x12\x1c.content.roles.CreateRequest\x1a\x1d.content.roles.CreateResponse\"\x00\x12>\n\x03Get\x12\x19.content.roles.GetRequest\x1a\x1a.content.roles.GetResponse\"\x00\x12@\n\x06Update\x12\x1c.content.roles.UpdateRequest\x1a\x16.google.protobuf.Empty\"\x00\x12\x41\n\x04List\x12\x1a.content.roles.ListRequest\x1a\x1b.content.roles.ListResponse\"\x00\x12@\n\x06\x44\x65lete\x12\x1c.content.roles.DeleteRequest\x1a\x16.google.protobuf.Empty\"\x00\x42.Z,github.com/perxteam/perxis/proto/roles;rolesb\x06proto3'
   ,
   dependencies=[google_dot_protobuf_dot_empty__pb2.DESCRIPTOR,perxis_dot_common_dot_common__pb2.DESCRIPTOR,])
 
@@ -64,6 +64,13 @@ _ROLE = _descriptor.Descriptor(
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
+    _descriptor.FieldDescriptor(
+      name='environments', full_name='content.roles.Role.environments', index=4,
+      number=5, type=9, cpp_type=9, label=3,
+      has_default_value=False, default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      serialized_options=None, file=DESCRIPTOR,  create_key=_descriptor._internal_create_key),
   ],
   extensions=[
   ],
@@ -77,7 +84,7 @@ _ROLE = _descriptor.Descriptor(
   oneofs=[
   ],
   serialized_start=100,
-  serialized_end=186,
+  serialized_end=208,
 )
 
 
@@ -108,8 +115,8 @@ _CREATEREQUEST = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=188,
-  serialized_end=238,
+  serialized_start=210,
+  serialized_end=260,
 )
 
 
@@ -140,8 +147,8 @@ _CREATERESPONSE = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=240,
-  serialized_end=294,
+  serialized_start=262,
+  serialized_end=316,
 )
 
 
@@ -179,8 +186,8 @@ _GETREQUEST = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=296,
-  serialized_end=343,
+  serialized_start=318,
+  serialized_end=365,
 )
 
 
@@ -211,8 +218,8 @@ _GETRESPONSE = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=345,
-  serialized_end=393,
+  serialized_start=367,
+  serialized_end=415,
 )
 
 
@@ -243,8 +250,8 @@ _UPDATEREQUEST = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=395,
-  serialized_end=445,
+  serialized_start=417,
+  serialized_end=467,
 )
 
 
@@ -275,8 +282,8 @@ _LISTREQUEST = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=447,
-  serialized_end=478,
+  serialized_start=469,
+  serialized_end=500,
 )
 
 
@@ -307,8 +314,8 @@ _LISTRESPONSE = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=480,
-  serialized_end=530,
+  serialized_start=502,
+  serialized_end=552,
 )
 
 
@@ -346,8 +353,8 @@ _DELETEREQUEST = _descriptor.Descriptor(
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=532,
-  serialized_end=582,
+  serialized_start=554,
+  serialized_end=604,
 )
 
 _ROLE.fields_by_name['rules'].message_type = perxis_dot_common_dot_common__pb2._RULE
@@ -440,8 +447,8 @@ _ROLES = _descriptor.ServiceDescriptor(
   index=0,
   serialized_options=None,
   create_key=_descriptor._internal_create_key,
-  serialized_start=585,
-  serialized_end=928,
+  serialized_start=607,
+  serialized_end=950,
   methods=[
   _descriptor.MethodDescriptor(
     name='Create',
diff --git a/proto/perxis/clients/clients.proto b/proto/perxis/clients/clients.proto
index c80838ed161c5cfd2d7a3839599423a8bab50bd1..1b1fd4c56e3cc1f24a4e4dd289ca67295487d233 100644
--- a/proto/perxis/clients/clients.proto
+++ b/proto/perxis/clients/clients.proto
@@ -8,15 +8,38 @@ option go_package = "github.com/perxteam/perxis/proto/clients;clients";
 package content.clients;
 
 message Client {
+  // Внутренний идентификатор клиента внутри системы
   string id = 1;
+
+  // Идентификатор пространства
   string space_id = 2;
+
+  // Имя приложения (обязательное поле)
   string name = 3;
+
+  // Идентификатор клиента выданные IdP сервером, используется для идентификации клиента
   string client_id = 4;
+
+  // Сервис который используется для авторизации клиента
   string auth_id = 5;
+
+  // Описание клиента, назначение
   string description = 6;
+
+  // Приложение отключено и не может авторизоваться
   optional bool disabled = 7;
+
+  // Приложение имеет доступ к указанным окружениям пространства (ID или Alias)
   repeated string environments = 8;
+
+  // Список правил доступа к коллекциям
   repeated common.Rule rules = 9;
+
+  // URL для получения/обновления access token клиента (опционально)
+  string token_url = 10;
+
+  // Секретный Ключ клиента, используется для идентификации клиента (опционально)
+  string client_secret = 11;
 }
 
 message CreateRequest {
diff --git a/proto/perxis/collections/collections.proto b/proto/perxis/collections/collections.proto
index 38d9380d95e1c5857f74d3377501feffc5e7b8ac..41ebe99aeeda8a168c3ae9c4a72b70acf4ba75ec 100644
--- a/proto/perxis/collections/collections.proto
+++ b/proto/perxis/collections/collections.proto
@@ -1,8 +1,8 @@
 syntax = "proto3";
 
 import "google/protobuf/empty.proto";
-//import "google/protobuf/wrappers.proto";
 import "perxis/common/common.proto";
+import "google/protobuf/timestamp.proto";
 
 option go_package = "github.com/perxteam/perxis/proto/collections;collections";
 
@@ -23,6 +23,7 @@ message Collection {
   optional bool single = 5;
   optional bool system = 6;
   string schema = 7;
+  string feature = 8;
 
   message View {
     string space_id = 1;
@@ -32,6 +33,20 @@ message Collection {
   }
   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;
 }
 
diff --git a/proto/perxis/common/common.proto b/proto/perxis/common/common.proto
index 337d0a8a489e83b56330bff1ca5ac7ef2b2563d8..51b9a5506e5e0c6beb21adff4c1cdf65b00a9f87 100644
--- a/proto/perxis/common/common.proto
+++ b/proto/perxis/common/common.proto
@@ -78,7 +78,8 @@ message Rule {
   repeated string hidden_fields = 5;
   repeated string readonly_fields = 6;
   repeated string writeonly_fields = 7;
-  string filter = 8;
+  string read_filter = 8;
+  string write_filter = 9;
 }
 
 message Collaborator {
diff --git a/proto/perxis/delivery/delivery.proto b/proto/perxis/delivery/delivery.proto
index 2245f2796ec7c2e6bc986acaecac2bd5af22dd3c..b833155fc91f579e8118dbca27fd6c5468395066 100644
--- a/proto/perxis/delivery/delivery.proto
+++ b/proto/perxis/delivery/delivery.proto
@@ -66,7 +66,6 @@ message FindItemsRequest {
   string space_id = 1;
   string env_id = 2;
   string collection_id = 3;
-  string locale_id = 4;
   content.items.Filter filter = 5;
   content.items.FindPublishedOptions options = 6;
 }
diff --git a/proto/perxis/references/references.proto b/proto/perxis/references/references.proto
new file mode 100644
index 0000000000000000000000000000000000000000..1141ee8fbb5ef352b4ad42035d52fdea42e2de13
--- /dev/null
+++ b/proto/perxis/references/references.proto
@@ -0,0 +1,30 @@
+syntax = "proto3";
+
+import "perxis/items/items.proto";
+
+option go_package = "github.com/perxteam/perxis/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/perxis/roles/roles.proto b/proto/perxis/roles/roles.proto
index 28c454761c8cd8077396cecc063dda75a70bfcee..c1dae47f61cfb6f1351560f181c2579dc22da452 100644
--- a/proto/perxis/roles/roles.proto
+++ b/proto/perxis/roles/roles.proto
@@ -8,10 +8,20 @@ option go_package = "github.com/perxteam/perxis/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;
 }
 
 message CreateRequest {
diff --git a/requirements.txt b/requirements.txt
index 59ba16f3ddd274e6f4e7fafcfca706412244ebdd..af76aec980d3224574b9c46e1daadef52f6b0853 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,11 +1,12 @@
-certifi==2021.5.30
+certifi==2021.10.8
 chardet==4.0.0
-grpcio==1.39.0
-idna==3.2
+charset-normalizer==2.0.9
+grpcio==1.42.0
+idna==3.3
 oauthlib==3.1.1
-protobuf==3.17.3
-PyJWT==2.1.0
+protobuf==3.19.1
+PyJWT==2.3.0
 requests==2.26.0
 requests-oauthlib==1.3.0
 six==1.16.0
-urllib3==1.26.6
+urllib3==1.26.7
diff --git a/setup.py b/setup.py
index f0f61e5a7a468cab2228c53b0636d7a9286a359a..6ad4852ce5a11306d03604f2bd4079a2103e0561 100644
--- a/setup.py
+++ b/setup.py
@@ -14,7 +14,7 @@ def load_requirements():
 
 setup(
     name='perxis',
-    version='0.0.4',
+    version='0.0.5',
     description='Perxis python client',
     long_description=long_description,
     long_description_content_type='text/markdown',