diff --git a/id/client.go b/id/client.go
index d2a8d0bc2edbe0f191bf9396135137441084776a..704f8d5f27f756f1f65d73ab138f08cc090bdf7d 100644
--- a/id/client.go
+++ b/id/client.go
@@ -1,6 +1,10 @@
 package id
 
-import "fmt"
+import (
+	"fmt"
+
+	"git.perx.ru/perxis/perxis-go/pkg/clients"
+)
 
 const (
 	Client        = "client"
@@ -26,7 +30,7 @@ func (id *ClientId) String() string {
 
 func (id *ClientId) FromParts(parts []string) error {
 	if len(parts) != 4 || parts[2] != ClientsPrefix {
-		return ErrInvalid
+		return ErrInvalidID
 	}
 	if err := id.SpaceId.FromParts(parts[:2]); err != nil {
 		return err
@@ -45,15 +49,19 @@ func (id *ClientId) Map() map[string]any {
 func (id *ClientId) FromMap(m map[string]any) error {
 	id.ClientID, _ = m["client_id"].(string)
 	if id.ClientID == "" {
-		return fmt.Errorf("%w: ClientID required", ErrInvalid)
+		return fmt.Errorf("%w: ClientID required", ErrInvalidID)
 	}
 	return id.SpaceId.FromMap(m)
 }
 
 func (id *ClientId) Validate() error {
 	if id.ClientID == "" {
-		return fmt.Errorf("%w: ClientID required", ErrInvalid)
+		return fmt.Errorf("%w: ClientID required", ErrInvalidID)
 	}
 
 	return id.SpaceId.Validate()
 }
+
+func NewClientId(c clients.Client) *ObjectId {
+	return &ObjectId{Descriptor: &ClientId{SpaceId: SpaceId{SpaceID: c.SpaceID}, ClientID: c.ID}}
+}
diff --git a/id/collection.go b/id/collection.go
index 49826e7a83cb5540b55830fdb8074a162ec73b2c..6518513b59238f0377aafe495dd4cac1f43a8436 100644
--- a/id/collection.go
+++ b/id/collection.go
@@ -1,6 +1,10 @@
 package id
 
-import "fmt"
+import (
+	"fmt"
+
+	"git.perx.ru/perxis/perxis-go/pkg/collections"
+)
 
 const (
 	Collection        = "collection"
@@ -15,7 +19,7 @@ type CollectionId struct {
 }
 
 func (id *CollectionId) New() Descriptor {
-	return &CollectionId{}
+	return &CollectionId{EnvironmentId: EnvironmentId{SpaceId: SpaceId{}}}
 }
 
 func (id *CollectionId) Type() string { return Collection }
@@ -33,7 +37,7 @@ func (id *CollectionId) Map() map[string]any {
 
 func (id *CollectionId) FromParts(parts []string) error {
 	if len(parts) != 6 || parts[4] != CollectionsPrefix {
-		return ErrInvalid
+		return ErrInvalidID
 	}
 	if err := id.EnvironmentId.FromParts(parts[:4]); err != nil {
 		return err
@@ -45,14 +49,26 @@ func (id *CollectionId) FromParts(parts []string) error {
 func (id *CollectionId) FromMap(m map[string]any) error {
 	id.CollectionID, _ = m["col_id"].(string)
 	if id.CollectionID == "" {
-		return fmt.Errorf("%w: CollectionID required", ErrInvalid)
+		return fmt.Errorf("%w: CollectionID required", ErrInvalidID)
 	}
 	return id.EnvironmentId.FromMap(m)
 }
 
 func (id *CollectionId) Validate() error {
 	if id.CollectionID == "" {
-		return fmt.Errorf("%w: CollectionID required", ErrInvalid)
+		return fmt.Errorf("%w: CollectionID required", ErrInvalidID)
 	}
 	return id.EnvironmentId.Validate()
 }
+
+func NewCollectionId(coll collections.Collection) *ObjectId {
+	return &ObjectId{Descriptor: &CollectionId{
+		EnvironmentId: EnvironmentId{
+			SpaceId: SpaceId{
+				SpaceID: coll.SpaceID,
+			},
+			EnvironmentID: coll.EnvID,
+		},
+		CollectionID: coll.ID,
+	}}
+}
diff --git a/id/environment.go b/id/environment.go
index 6c09603d14371f2f305c59fb8e318fd18a3fe828..0da72195ae0e1bc9d9262e6b958f61c30c0a2f36 100644
--- a/id/environment.go
+++ b/id/environment.go
@@ -2,6 +2,8 @@ package id
 
 import (
 	"fmt"
+
+	"git.perx.ru/perxis/perxis-go/pkg/environments"
 )
 
 const (
@@ -9,6 +11,8 @@ const (
 	EnvironmentsPrefix = "envs"
 )
 
+var _ Descriptor = &EnvironmentId{}
+
 type EnvironmentId struct {
 	SpaceId
 	EnvironmentID string `json:"env_id,omitempty" bson:"env_id,omitempty"`
@@ -34,7 +38,7 @@ func (id *EnvironmentId) Map() map[string]any {
 
 func (id *EnvironmentId) FromParts(parts []string) error {
 	if len(parts) != 4 || parts[2] != EnvironmentsPrefix {
-		return ErrInvalid
+		return ErrInvalidID
 	}
 	if err := id.SpaceId.FromParts(parts[:2]); err != nil {
 		return err
@@ -46,14 +50,22 @@ func (id *EnvironmentId) FromParts(parts []string) error {
 func (id *EnvironmentId) FromMap(m map[string]any) error {
 	id.EnvironmentID, _ = m["env_id"].(string)
 	if id.EnvironmentID == "" {
-		return fmt.Errorf("%w: EnviromentID required", ErrInvalid)
+		return fmt.Errorf("%w: EnviromentID required", ErrInvalidID)
 	}
 	return id.SpaceId.FromMap(m)
 }
 
 func (id *EnvironmentId) Validate() error {
 	if id.EnvironmentID == "" {
-		return fmt.Errorf("%w: EnvironmetnID required", ErrInvalid)
+		return fmt.Errorf("%w: EnvironmetnID required", ErrInvalidID)
 	}
 	return id.SpaceId.Validate()
 }
+func NewEnvironmentId(env environments.Environment) *ObjectId {
+	return &ObjectId{Descriptor: &EnvironmentId{
+		SpaceId: SpaceId{
+			SpaceID: env.SpaceID,
+		},
+		EnvironmentID: env.ID,
+	}}
+}
diff --git a/id/error.go b/id/error.go
index 3622b5d1678418d7ff0e05660491fa6791ff07cd..e8332dc96a651e337cdc34ec83d06442ff27048e 100644
--- a/id/error.go
+++ b/id/error.go
@@ -3,8 +3,8 @@ package id
 import "errors"
 
 var (
-	ErrInvalidID         = errors.New("invalid ObjectId")
-	ErrUnknownType         = errors.New("unknown ObjectId type")
+	ErrInvalidID       = errors.New("invalid ObjectId")
+	ErrUnknownType     = errors.New("unknown ObjectId type")
 	ErrHandlerNotFound = errors.New("ObjectId handler not found")
 	ErrTypeNotFound    = errors.New("type key not found in map")
 	ErrInvalidType     = errors.New("ObjectId should be a string")
diff --git a/id/field.go b/id/field.go
index 0310c9165a420af3b60cab3df32e796e8e6e0894..024732f2d44d7a2ac4db63418ba113563a379c8d 100644
--- a/id/field.go
+++ b/id/field.go
@@ -12,6 +12,8 @@ type FieldId struct {
 	Field string `json:"field,omitempty" bson:"field,omitempty"`
 }
 
+var _ Descriptor = &FieldId{}
+
 func (id *FieldId) New() Descriptor {
 	return &FieldId{}
 }
@@ -25,7 +27,7 @@ func (id *FieldId) String() string {
 
 func (id *FieldId) FromParts(parts []string) error {
 	if len(parts) != 10 || parts[8] != FieldsPrefix {
-		return ErrInvalid
+		return ErrInvalidID
 	}
 	if err := id.ItemId.FromParts(parts[:8]); err != nil {
 		return err
@@ -44,7 +46,7 @@ func (id *FieldId) Map() map[string]any {
 func (id *FieldId) FromMap(m map[string]any) error {
 	id.Field = m["field"].(string)
 	if id.Field == "" {
-		return fmt.Errorf("%w: Field required", ErrInvalid)
+		return fmt.Errorf("%w: Field required", ErrInvalidID)
 	}
 
 	if err := id.ItemId.FromMap(m); err != nil {
@@ -55,8 +57,26 @@ func (id *FieldId) FromMap(m map[string]any) error {
 
 func (id *FieldId) Validate() error {
 	if id.Field == "" {
-		return fmt.Errorf("%w: Field required", ErrInvalid)
+		return fmt.Errorf("%w: Field required", ErrInvalidID)
 	}
 
 	return id.ItemId.Validate()
 }
+
+func NewFieldId(spaceID, envID, collID, itemID, id string) *ObjectId {
+	return &ObjectId{Descriptor: &FieldId{
+		ItemId: ItemId{
+			CollectionId: CollectionId{
+				EnvironmentId: EnvironmentId{
+					SpaceId: SpaceId{
+						SpaceID: spaceID,
+					},
+					EnvironmentID: envID,
+				},
+				CollectionID: collID,
+			},
+			ItemID: itemID,
+		},
+		Field: id,
+	}}
+}
diff --git a/id/item.go b/id/item.go
index 01410c4b7a3cd26ecb827ffbcc60868757747561..dbfb8e18cb5128fc0ab26a4298203a38a4af1ad6 100644
--- a/id/item.go
+++ b/id/item.go
@@ -1,6 +1,10 @@
 package id
 
-import "fmt"
+import (
+	"fmt"
+
+	"git.perx.ru/perxis/perxis-go/pkg/items"
+)
 
 const (
 	Item        = "item"
@@ -12,6 +16,8 @@ type ItemId struct {
 	ItemID string `json:"item_id,omitempty" bson:"item_id,omitempty"`
 }
 
+var _ Descriptor = &ItemId{}
+
 func (i *ItemId) New() Descriptor {
 	return &ItemId{}
 }
@@ -32,7 +38,7 @@ func (i *ItemId) Map() map[string]any {
 
 func (i *ItemId) FromParts(parts []string) error {
 	if len(parts) != 8 || parts[6] != ItemsPrefix {
-		return ErrInvalid
+		return ErrInvalidID
 	}
 
 	if err := i.CollectionId.FromParts(parts[:6]); err != nil {
@@ -46,7 +52,7 @@ func (i *ItemId) FromParts(parts []string) error {
 func (i *ItemId) FromMap(m map[string]any) error {
 	i.ItemID = m["item_id"].(string)
 	if i.ItemID == "" {
-		return fmt.Errorf("%w: ItemId required", ErrInvalid)
+		return fmt.Errorf("%w: ItemId required", ErrInvalidID)
 	}
 
 	return i.CollectionId.FromMap(m)
@@ -54,7 +60,21 @@ func (i *ItemId) FromMap(m map[string]any) error {
 
 func (i *ItemId) Validate() error {
 	if i.ItemID == "" {
-		return fmt.Errorf("%w: ItemId required", ErrInvalid)
+		return fmt.Errorf("%w: ItemId required", ErrInvalidID)
 	}
 	return i.CollectionId.Validate()
 }
+func NewItemId(i items.Item) *ObjectId {
+	return &ObjectId{Descriptor: &ItemId{
+		CollectionId: CollectionId{
+			EnvironmentId: EnvironmentId{
+				SpaceId: SpaceId{
+					SpaceID: i.SpaceID,
+				},
+				EnvironmentID: i.EnvID,
+			},
+			CollectionID: i.CollectionID,
+		},
+		ItemID: i.ID,
+	}}
+}
diff --git a/id/organization.go b/id/organization.go
index 7f03bb98233eae72b7a3c296d3de687d5455a0e5..03fd47fc9f51fbdb67c219c6a636f0f117d032c7 100644
--- a/id/organization.go
+++ b/id/organization.go
@@ -1,6 +1,10 @@
 package id
 
-import "fmt"
+import (
+	"fmt"
+
+	"git.perx.ru/perxis/perxis-go/pkg/organizations"
+)
 
 const (
 	Organization        = "organization"
@@ -25,7 +29,7 @@ func (id *OrganizationId) String() string {
 
 func (id *OrganizationId) FromParts(parts []string) error {
 	if len(parts) != 2 || parts[0] != OrganizationsPrefix {
-		return ErrInvalid
+		return ErrInvalidID
 	}
 	id.OrganizationID = parts[1]
 	return nil
@@ -41,14 +45,18 @@ func (id *OrganizationId) Map() map[string]any {
 func (id *OrganizationId) FromMap(m map[string]any) error {
 	id.OrganizationID, _ = m["organization_id"].(string)
 	if id.OrganizationID == "" {
-		return fmt.Errorf("%w: OrganizationId required", ErrInvalid)
+		return fmt.Errorf("%w: OrganizationId required", ErrInvalidID)
 	}
 	return nil
 }
 
 func (id *OrganizationId) Validate() error {
 	if id.OrganizationID == "" {
-		return fmt.Errorf("%w: OrganizationId required", ErrInvalid)
+		return fmt.Errorf("%w: OrganizationId required", ErrInvalidID)
 	}
 	return nil
 }
+
+func NewOrganizationId(o organizations.Organization) *ObjectId {
+	return &ObjectId{Descriptor: &OrganizationId{OrganizationID: o.ID}}
+}
diff --git a/id/registry.go b/id/registry.go
index 7d12fe2f28af31a357ba6dea98273b7154b63016..89b779c96f98472f391073283274014ff1075756 100644
--- a/id/registry.go
+++ b/id/registry.go
@@ -40,7 +40,7 @@ func (r *Registry) FromParts(s string) (*ObjectId, error) {
 		}
 	}
 
-	return nil, fmt.Errorf("%w: %s", ErrInvalid, s)
+	return nil, fmt.Errorf("%w: %s", ErrInvalidID, s)
 }
 
 func (r *Registry) FromMap(m map[string]interface{}) (*ObjectId, error) {
@@ -57,11 +57,13 @@ func (r *Registry) FromMap(m map[string]interface{}) (*ObjectId, error) {
 		return &ObjectId{Descriptor: id}, nil
 	}
 
-	return nil, fmt.Errorf("%s: %s", t, ErrInvalid)
+	return nil, fmt.Errorf("%s: %s", t, ErrInvalidID)
 }
 
 func (r *Registry) FromObject(v interface{}) (*ObjectId, error) {
 	t := reflect.TypeOf(v)
+	fmt.Println(t.String())
+	fmt.Println(r.handlers)
 	if handler, ok := r.handlers[t]; ok {
 		i := handler(v)
 		if i == nil {
diff --git a/id/revision.go b/id/revision.go
index 6d6c369fd78af30d228603f95dd77fada46a967b..f8a2ecb4b893d71734e72bd1911a32173a3fd17c 100644
--- a/id/revision.go
+++ b/id/revision.go
@@ -12,6 +12,8 @@ type RevisionId struct {
 	RevisionID string `json:"rev_id" bson:"rev_id,omitempty"`
 }
 
+var _ Descriptor = &RevisionId{}
+
 func (id *RevisionId) New() Descriptor {
 	return &RevisionId{}
 }
@@ -25,7 +27,7 @@ func (id *RevisionId) String() string {
 
 func (id *RevisionId) FromParts(parts []string) error {
 	if len(parts) != 10 || parts[8] != RevisionsPrefix {
-		return ErrInvalid
+		return ErrInvalidID
 	}
 	if err := id.ItemId.FromParts(parts[:8]); err != nil {
 		return err
@@ -44,7 +46,7 @@ func (id *RevisionId) Map() map[string]any {
 func (id *RevisionId) FromMap(m map[string]any) error {
 	id.RevisionID = m["rev_id"].(string)
 	if id.RevisionID == "" {
-		return fmt.Errorf("%w: RevisionId required", ErrInvalid)
+		return fmt.Errorf("%w: RevisionId required", ErrInvalidID)
 	}
 
 	if err := id.ItemId.FromMap(m); err != nil {
@@ -55,8 +57,26 @@ func (id *RevisionId) FromMap(m map[string]any) error {
 
 func (id *RevisionId) Validate() error {
 	if id.RevisionID == "" {
-		return fmt.Errorf("%w: RevisionId required", ErrInvalid)
+		return fmt.Errorf("%w: RevisionId required", ErrInvalidID)
 	}
 
 	return id.ItemId.Validate()
 }
+
+func NewRevisionID(spaceID, envID, collID, itemID, id string) *ObjectId {
+	return &ObjectId{Descriptor: &RevisionId{
+		ItemId: ItemId{
+			CollectionId: CollectionId{
+				EnvironmentId: EnvironmentId{
+					SpaceId: SpaceId{
+						SpaceID: spaceID,
+					},
+					EnvironmentID: envID,
+				},
+				CollectionID: collID,
+			},
+			ItemID: itemID,
+		},
+		RevisionID: id,
+	}}
+}
diff --git a/id/role.go b/id/role.go
index 6644aea412de16bcc3dd1fb5d22a0e70958e402e..4e507d92e6443a7bd890fd5ea0414c1fddebb3c3 100644
--- a/id/role.go
+++ b/id/role.go
@@ -1,6 +1,10 @@
 package id
 
-import "fmt"
+import (
+	"fmt"
+
+	"git.perx.ru/perxis/perxis-go/pkg/roles"
+)
 
 const (
 	Role        = "role"
@@ -26,7 +30,7 @@ func (id *RoleId) String() string {
 
 func (id *RoleId) FromParts(parts []string) error {
 	if len(parts) != 4 || parts[2] != RolesPrefix {
-		return ErrInvalid
+		return ErrInvalidID
 	}
 	if err := id.SpaceId.FromParts(parts[:2]); err != nil {
 		return err
@@ -45,15 +49,23 @@ func (id *RoleId) Map() map[string]any {
 func (id *RoleId) FromMap(m map[string]any) error {
 	id.RoleID = m["role_id"].(string)
 	if id.RoleID == "" {
-		return fmt.Errorf("%w: RoleID required", ErrInvalid)
+		return fmt.Errorf("%w: RoleID required", ErrInvalidID)
 	}
 	return id.SpaceId.FromMap(m)
 }
 
 func (id *RoleId) Validate() error {
 	if id.RoleID == "" {
-		return fmt.Errorf("%w: RoleID required", ErrInvalid)
+		return fmt.Errorf("%w: RoleID required", ErrInvalidID)
 	}
 
 	return id.SpaceId.Validate()
 }
+func NewRoleId(r roles.Role) *ObjectId {
+	return &ObjectId{Descriptor: &RoleId{
+		SpaceId: SpaceId{
+			SpaceID: r.SpaceID,
+		},
+		RoleID: r.ID,
+	}}
+}
diff --git a/id/schema.go b/id/schema.go
index ad59a14b55fe978a34c627e4a86ee0f14788873f..b1280f81ca440ae78ce128e471292e26a2db4a97 100644
--- a/id/schema.go
+++ b/id/schema.go
@@ -7,6 +7,8 @@ const (
 	SchemaPrefix = "schema"
 )
 
+var _ Descriptor = &SchemaId{}
+
 type SchemaId struct {
 	EnvironmentId
 	CollectionID string `json:"col_id" bson:"col_id,omitempty"`
@@ -31,7 +33,7 @@ func (id *SchemaId) Map() map[string]any {
 
 func (id *SchemaId) FromParts(parts []string) error {
 	if len(parts) != 6 || parts[4] != SchemaPrefix {
-		return ErrInvalid
+		return ErrInvalidID
 	}
 	if err := id.EnvironmentId.FromParts(parts[:4]); err != nil {
 		return err
@@ -43,14 +45,26 @@ func (id *SchemaId) FromParts(parts []string) error {
 func (id *SchemaId) FromMap(m map[string]any) error {
 	id.CollectionID, _ = m["col_id"].(string)
 	if id.CollectionID == "" {
-		return fmt.Errorf("%w: SchemaID required", ErrInvalid)
+		return fmt.Errorf("%w: SchemaID required", ErrInvalidID)
 	}
 	return id.EnvironmentId.FromMap(m)
 }
 
 func (id *SchemaId) Validate() error {
 	if id.CollectionID == "" {
-		return fmt.Errorf("%w: SchemaID required", ErrInvalid)
+		return fmt.Errorf("%w: SchemaID required", ErrInvalidID)
 	}
 	return id.EnvironmentId.Validate()
 }
+
+func NewSchemaId(spaceID, envID, id string) *ObjectId {
+	return &ObjectId{Descriptor: &SchemaId{
+		EnvironmentId: EnvironmentId{
+			SpaceId: SpaceId{
+				SpaceID: spaceID,
+			},
+			EnvironmentID: envID,
+		},
+		CollectionID: id,
+	}}
+}
diff --git a/id/service.go b/id/service.go
index 08dba5392de6da2cc1309a93c5a49ffe678e4e4e..29c44ec635f763b9f35223f710f2d530f2dfb159 100644
--- a/id/service.go
+++ b/id/service.go
@@ -25,7 +25,7 @@ func (id *ServiceId) String() string {
 
 func (id *ServiceId) FromParts(parts []string) error {
 	if len(parts) != 2 || parts[0] != ServicesPrefix {
-		return ErrInvalid
+		return ErrInvalidID
 	}
 	id.ServiceID = parts[1]
 	return nil
@@ -41,14 +41,18 @@ func (id *ServiceId) Map() map[string]any {
 func (id *ServiceId) FromMap(m map[string]any) error {
 	id.ServiceID, _ = m["service_id"].(string)
 	if id.ServiceID == "" {
-		return fmt.Errorf("%w: ServiceId required", ErrInvalid)
+		return fmt.Errorf("%w: ServiceId required", ErrInvalidID)
 	}
 	return nil
 }
 
 func (id *ServiceId) Validate() error {
 	if id.ServiceID == "" {
-		return fmt.Errorf("%w: ServiceId required", ErrInvalid)
+		return fmt.Errorf("%w: ServiceId required", ErrInvalidID)
 	}
 	return nil
 }
+
+func NewServiceID(id string) *ObjectId {
+	return &ObjectId{Descriptor: &ServiceId{ServiceID: id}}
+}
diff --git a/id/space.go b/id/space.go
index 2cd8d1430a0f8086c6e4cedcf2a20d1cd9499ba4..a9d88bc66ba8105f00825674a2015ea16779860f 100644
--- a/id/space.go
+++ b/id/space.go
@@ -2,6 +2,8 @@ package id
 
 import (
 	"fmt"
+
+	"git.perx.ru/perxis/perxis-go/pkg/spaces"
 )
 
 const (
@@ -27,7 +29,7 @@ func (id *SpaceId) String() string {
 
 func (id *SpaceId) FromParts(parts []string) error {
 	if len(parts) != 2 || parts[0] != SpacesPrefix {
-		return ErrInvalid
+		return ErrInvalidID
 	}
 
 	id.SpaceID = parts[1]
@@ -44,14 +46,18 @@ func (id *SpaceId) Map() map[string]any {
 func (id *SpaceId) FromMap(m map[string]any) error {
 	id.SpaceID, _ = m["space_id"].(string)
 	if id.SpaceID == "" {
-		return fmt.Errorf("%w: SpaceId required", ErrInvalid)
+		return fmt.Errorf("%w: SpaceId required", ErrInvalidID)
 	}
 	return nil
 }
 
 func (id *SpaceId) Validate() error {
 	if id.SpaceID == "" {
-		return fmt.Errorf("%w: SpaceId required", ErrInvalid)
+		return fmt.Errorf("%w: SpaceId required", ErrInvalidID)
 	}
 	return nil
 }
+
+func NewSpaceId(s spaces.Space) *ObjectId {
+	return &ObjectId{Descriptor: &SpaceId{SpaceID: s.ID}}
+}
diff --git a/id/system.go b/id/system.go
index 3efa4b9c927f9861b1cf8e4bc199611eb0dd006b..28eb6e04f4e5e7eff20e2b4218c33f8bdcec1fc9 100644
--- a/id/system.go
+++ b/id/system.go
@@ -4,6 +4,8 @@ const System = "system"
 
 type SystemId struct{}
 
+var _ Descriptor = &SystemId{}
+
 func (id *SystemId) New() Descriptor {
 	return &SystemId{}
 }
@@ -12,10 +14,11 @@ func (id *SystemId) Type() string   { return System }
 func (id *SystemId) String() string { return string(Separator) + System }
 func (id *SystemId) FromParts(parts []string) error {
 	if len(parts) != 1 || parts[0] != System {
-		return ErrInvalid
+		return ErrInvalidID
 	}
 	return nil
 }
 func (id *SystemId) Map() map[string]any            { return map[string]any{"type": System} }
 func (id *SystemId) FromMap(m map[string]any) error { return nil }
 func (id *SystemId) Validate() error                { return nil }
+func (id *SystemId) NewSystemId() *ObjectId         { return &ObjectId{Descriptor: &SystemId{}} }
diff --git a/id/system/system.go b/id/system/system.go
index 713fca341268bdda5fcbc6eb553741913be67af3..77084f5dcb8dc702b2b14337e97cdc97fd80930b 100644
--- a/id/system/system.go
+++ b/id/system/system.go
@@ -6,6 +6,7 @@ import (
 
 	"git.perx.ru/perxis/perxis-go/id"
 	"git.perx.ru/perxis/perxis-go/pkg/auth"
+	"git.perx.ru/perxis/perxis-go/pkg/clients"
 	"git.perx.ru/perxis/perxis-go/pkg/collections"
 	"git.perx.ru/perxis/perxis-go/pkg/environments"
 	"git.perx.ru/perxis/perxis-go/pkg/items"
@@ -17,6 +18,10 @@ import (
 
 func Handler(obj any) *id.ObjectId {
 	switch val := obj.(type) {
+	case *organizations.Organization:
+		var i id.OrganizationId
+		i.OrganizationID = val.ID
+		return id.MustObjectId(&i)
 	case *spaces.Space:
 		var i id.SpaceId
 		i.SpaceID = val.ID
@@ -43,9 +48,10 @@ func Handler(obj any) *id.ObjectId {
 		var i id.UserId
 		i.UserID = val.ID
 		return id.MustObjectId(&i)
-	case *organizations.Organization:
-		var i id.OrganizationId
-		i.OrganizationID = val.ID
+	case *clients.Client:
+		var i id.ClientId
+		i.SpaceID = val.SpaceID
+		i.ClientID = val.ID
 		return id.MustObjectId(&i)
 	case *roles.Role:
 		var i id.RoleId
@@ -77,13 +83,13 @@ func Register(r *id.Registry) {
 	r.RegisterObjectHandler(reflect.TypeOf(&environments.Environment{}), Handler)
 	r.RegisterObjectHandler(reflect.TypeOf(&collections.Collection{}), Handler)
 	r.RegisterObjectHandler(reflect.TypeOf(&items.Item{}), Handler)
+	r.RegisterObjectHandler(reflect.TypeOf(&clients.Client{}), Handler)
 	r.RegisterObjectHandler(reflect.TypeOf(&roles.Role{}), Handler)
+	r.RegisterObjectHandler(reflect.TypeOf(&users.User{}), Handler)
 	r.RegisterObjectHandler(reflect.TypeOf(&auth.UserPrincipal{}), Handler)
 	r.RegisterObjectHandler(reflect.TypeOf(&auth.ClientPrincipal{}), Handler)
 	r.RegisterObjectHandler(reflect.TypeOf(&auth.SystemPrincipal{}), Handler)
 	r.RegisterObjectHandler(reflect.TypeOf(&auth.Anonymous{}), Handler)
-
-	// TODO: Добавить регистрацию schema, revision, service непонятно как делать
 }
 
 func init() {
diff --git a/id/test/object_id_test.go b/id/test/object_id_test.go
index 437b3bb2fb62797d1c3a93858f2ff408238b0ce1..f97e50e49068173b5aa1968de33abc4d8a44817b 100644
--- a/id/test/object_id_test.go
+++ b/id/test/object_id_test.go
@@ -1,16 +1,180 @@
 package test
 
 import (
+	"testing"
+
 	"git.perx.ru/perxis/perxis-go/id"
 	_ "git.perx.ru/perxis/perxis-go/id/system"
+	"git.perx.ru/perxis/perxis-go/pkg/clients"
 	"git.perx.ru/perxis/perxis-go/pkg/collections"
 	"git.perx.ru/perxis/perxis-go/pkg/environments"
 	"git.perx.ru/perxis/perxis-go/pkg/items"
+	"git.perx.ru/perxis/perxis-go/pkg/organizations"
+	"git.perx.ru/perxis/perxis-go/pkg/roles"
 	"git.perx.ru/perxis/perxis-go/pkg/spaces"
+	"git.perx.ru/perxis/perxis-go/pkg/users"
 	"github.com/stretchr/testify/require"
-	"testing"
 )
 
+func Test_OrganizationId(t *testing.T) {
+
+	tests := []struct {
+		name   string
+		in     any
+		out    string
+		result *id.ObjectId
+		err    error
+	}{
+		{
+			name:   "valid string",
+			in:     "/orgs/<org_id>",
+			result: &id.ObjectId{Descriptor: &id.OrganizationId{OrganizationID: "<org_id>"}},
+		},
+		{
+			name:   "valid object",
+			in:     &organizations.Organization{ID: "<org_id>"},
+			out:    "/orgs/<org_id>",
+			result: &id.ObjectId{Descriptor: &id.OrganizationId{OrganizationID: "<org_id>"}},
+		},
+		{
+			name:   "valid map",
+			in:     map[string]any{"type": "organization", "organization_id": "<org_id>"},
+			out:    "/orgs/<org_id>",
+			result: &id.ObjectId{Descriptor: &id.OrganizationId{OrganizationID: "<org_id>"}},
+		},
+		{
+			name:   "invalid map",
+			in:     map[string]any{"type": "organization"},
+			out:    "/orgs/<org_id>",
+			result: &id.ObjectId{Descriptor: &id.OrganizationId{OrganizationID: "<org_id>"}},
+			err:    id.ErrInvalidID,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			i, err := id.NewObjectId(tt.in)
+
+			if tt.err != nil {
+				require.ErrorIs(t, err, tt.err)
+				return
+			}
+
+			require.NoError(t, err)
+			require.Equal(t, tt.result, i)
+			if tt.out == "" {
+				require.Equal(t, tt.in, i.String())
+			} else {
+				require.Equal(t, tt.out, i.String())
+			}
+		})
+	}
+}
+
+func Test_ServiceId(t *testing.T) {
+
+	tests := []struct {
+		name   string
+		in     any
+		out    string
+		result *id.ObjectId
+		err    error
+	}{
+		{
+			name:   "valid string",
+			in:     "/services/<service_id>",
+			result: &id.ObjectId{Descriptor: &id.ServiceId{ServiceID: "<service_id>"}},
+		},
+		{
+			name:   "valid map",
+			in:     map[string]any{"type": "service", "service_id": "<service_id>"},
+			out:    "/services/<service_id>",
+			result: &id.ObjectId{Descriptor: &id.ServiceId{ServiceID: "<service_id>"}},
+		},
+		{
+			name:   "invalid map",
+			in:     map[string]any{"type": "service"},
+			out:    "/services/<service_id>",
+			result: &id.ObjectId{Descriptor: &id.ServiceId{ServiceID: "<service_id>"}},
+			err:    id.ErrInvalidID,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			i, err := id.NewObjectId(tt.in)
+
+			if tt.err != nil {
+				require.ErrorIs(t, err, tt.err)
+				return
+			}
+
+			require.NoError(t, err)
+			require.Equal(t, tt.result, i)
+			if tt.out == "" {
+				require.Equal(t, tt.in, i.String())
+			} else {
+				require.Equal(t, tt.out, i.String())
+			}
+		})
+	}
+}
+
+func Test_UserId(t *testing.T) {
+
+	tests := []struct {
+		name   string
+		in     any
+		out    string
+		result *id.ObjectId
+		err    error
+	}{
+		{
+			name:   "valid string",
+			in:     "/users/<user_id>",
+			result: &id.ObjectId{Descriptor: &id.UserId{UserID: "<user_id>"}},
+		},
+		{
+			name:   "valid object",
+			in:     &users.User{ID: "<user_id>"},
+			out:    "/users/<user_id>",
+			result: &id.ObjectId{Descriptor: &id.UserId{UserID: "<user_id>"}},
+		},
+		{
+			name:   "valid map",
+			in:     map[string]any{"type": "user", "user_id": "<user_id>"},
+			out:    "/users/<user_id>",
+			result: &id.ObjectId{Descriptor: &id.UserId{UserID: "<user_id>"}},
+		},
+		{
+			name:   "invalid map",
+			in:     map[string]any{"type": "user"},
+			out:    "/users/<user_id>",
+			result: &id.ObjectId{Descriptor: &id.UserId{UserID: "<user_id>"}},
+			err:    id.ErrInvalidID,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			i, err := id.NewObjectId(tt.in)
+
+			if tt.err != nil {
+				require.ErrorIs(t, err, tt.err)
+				return
+			}
+
+			require.NoError(t, err)
+			require.Equal(t, tt.result, i)
+			if tt.out == "" {
+				require.Equal(t, tt.in, i.String())
+			} else {
+				require.Equal(t, tt.out, i.String())
+			}
+		})
+	}
+}
+
 func Test_SpaceId(t *testing.T) {
 
 	tests := []struct {
@@ -42,7 +206,7 @@ func Test_SpaceId(t *testing.T) {
 			in:     map[string]any{"type": "space"},
 			out:    "/spaces/<space_id>",
 			result: &id.ObjectId{Descriptor: &id.SpaceId{SpaceID: "<space_id>"}},
-			err:    id.ErrInvalid,
+			err:    id.ErrInvalidID,
 		},
 	}
 
@@ -90,7 +254,7 @@ func Test_EnvironmentId(t *testing.T) {
 				SpaceId:       id.SpaceId{SpaceID: "<space_id>"},
 				EnvironmentID: "<env_id>",
 			}},
-			err: id.ErrInvalid,
+			err: id.ErrInvalidID,
 		},
 		{
 			name: "valid object",
@@ -118,7 +282,7 @@ func Test_EnvironmentId(t *testing.T) {
 				SpaceId:       id.SpaceId{SpaceID: "<space_id>"},
 				EnvironmentID: "<env_id>",
 			}},
-			err: id.ErrInvalid,
+			err: id.ErrInvalidID,
 		},
 		{
 			name: "invalid map 2",
@@ -128,7 +292,179 @@ func Test_EnvironmentId(t *testing.T) {
 				SpaceId:       id.SpaceId{SpaceID: "<space_id>"},
 				EnvironmentID: "<env_id>",
 			}},
-			err: id.ErrInvalid,
+			err: id.ErrInvalidID,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			i, err := id.NewObjectId(tt.in)
+
+			if tt.err != nil {
+				require.ErrorIs(t, err, tt.err)
+				return
+			}
+
+			require.NoError(t, err)
+			require.Equal(t, tt.result, i)
+			if tt.out == "" {
+				require.Equal(t, tt.in, i.String())
+			} else {
+				require.Equal(t, tt.out, i.String())
+			}
+		})
+	}
+}
+
+func Test_ClientId(t *testing.T) {
+
+	tests := []struct {
+		name   string
+		in     any
+		out    string
+		result *id.ObjectId
+		err    error
+	}{
+		{
+			name: "valid string",
+			in:   "/spaces/<space_id>/clients/<client_id>",
+			result: &id.ObjectId{Descriptor: &id.ClientId{
+				SpaceId:  id.SpaceId{SpaceID: "<space_id>"},
+				ClientID: "<client_id>",
+			}},
+		},
+		{
+			name: "invalid string",
+			in:   "/clients/<client_id>",
+			result: &id.ObjectId{Descriptor: &id.ClientId{
+				SpaceId:  id.SpaceId{SpaceID: "<space_id>"},
+				ClientID: "<client_id>",
+			}},
+			err: id.ErrInvalidID,
+		},
+		{
+			name: "valid object",
+			in:   &clients.Client{SpaceID: "<space_id>", ID: "<client_id>"},
+			out:  "/spaces/<space_id>/clients/<client_id>",
+			result: &id.ObjectId{Descriptor: &id.ClientId{
+				SpaceId:  id.SpaceId{SpaceID: "<space_id>"},
+				ClientID: "<client_id>",
+			}},
+		},
+		{
+			name: "valid map",
+			in:   map[string]any{"type": "client", "space_id": "<space_id>", "client_id": "<client_id>"},
+			out:  "/spaces/<space_id>/clients/<client_id>",
+			result: &id.ObjectId{Descriptor: &id.ClientId{
+				SpaceId:  id.SpaceId{SpaceID: "<space_id>"},
+				ClientID: "<client_id>",
+			}},
+		},
+		{
+			name: "invalid map 1",
+			in:   map[string]any{"type": "client", "space_id": "<space_id>"},
+			out:  "/spaces/<space_id>/clients/<client_id>",
+			result: &id.ObjectId{Descriptor: &id.ClientId{
+				SpaceId:  id.SpaceId{SpaceID: "<space_id>"},
+				ClientID: "<client_id>",
+			}},
+			err: id.ErrInvalidID,
+		},
+		{
+			name: "invalid map 2",
+			in:   map[string]any{"type": "client", "client_id": "<client_id>"},
+			out:  "/spaces/<space_id>/clients/<client_id>",
+			result: &id.ObjectId{Descriptor: &id.ClientId{
+				SpaceId:  id.SpaceId{SpaceID: "<space_id>"},
+				ClientID: "<client_id>",
+			}},
+			err: id.ErrInvalidID,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			i, err := id.NewObjectId(tt.in)
+
+			if tt.err != nil {
+				require.ErrorIs(t, err, tt.err)
+				return
+			}
+
+			require.NoError(t, err)
+			require.Equal(t, tt.result, i)
+			if tt.out == "" {
+				require.Equal(t, tt.in, i.String())
+			} else {
+				require.Equal(t, tt.out, i.String())
+			}
+		})
+	}
+}
+
+func Test_RoleId(t *testing.T) {
+
+	tests := []struct {
+		name   string
+		in     any
+		out    string
+		result *id.ObjectId
+		err    error
+	}{
+		{
+			name: "valid string",
+			in:   "/spaces/<space_id>/roles/<role_id>",
+			result: &id.ObjectId{Descriptor: &id.RoleId{
+				SpaceId: id.SpaceId{SpaceID: "<space_id>"},
+				RoleID:  "<role_id>",
+			}},
+		},
+		{
+			name: "invalid string",
+			in:   "/roles/<role_id>",
+			result: &id.ObjectId{Descriptor: &id.RoleId{
+				SpaceId: id.SpaceId{SpaceID: "<space_id>"},
+				RoleID:  "<role_id>",
+			}},
+			err: id.ErrInvalidID,
+		},
+		{
+			name: "valid object",
+			in:   &roles.Role{SpaceID: "<space_id>", ID: "<role_id>"},
+			out:  "/spaces/<space_id>/roles/<role_id>",
+			result: &id.ObjectId{Descriptor: &id.RoleId{
+				SpaceId: id.SpaceId{SpaceID: "<space_id>"},
+				RoleID:  "<role_id>",
+			}},
+		},
+		{
+			name: "valid map",
+			in:   map[string]any{"type": "role", "space_id": "<space_id>", "role_id": "<role_id>"},
+			out:  "/spaces/<space_id>/roles/<role_id>",
+			result: &id.ObjectId{Descriptor: &id.RoleId{
+				SpaceId: id.SpaceId{SpaceID: "<space_id>"},
+				RoleID:  "<role_id>",
+			}},
+		},
+		{
+			name: "invalid map 1",
+			in:   map[string]any{"type": "client", "space_id": "<space_id>"},
+			out:  "/spaces/<space_id>/roles/<role_id>",
+			result: &id.ObjectId{Descriptor: &id.RoleId{
+				SpaceId: id.SpaceId{SpaceID: "<space_id>"},
+				RoleID:  "<role_id>",
+			}},
+			err: id.ErrInvalidID,
+		},
+		{
+			name: "invalid map 2",
+			in:   map[string]any{"type": "role", "role_id": "<role_id>"},
+			out:  "/spaces/<space_id>/roles/<role_id>",
+			result: &id.ObjectId{Descriptor: &id.RoleId{
+				SpaceId: id.SpaceId{SpaceID: "<space_id>"},
+				RoleID:  "<role_id>",
+			}},
+			err: id.ErrInvalidID,
 		},
 	}
 
@@ -187,7 +523,54 @@ func Test_CollectionId(t *testing.T) {
 				CollectionID:  "<collection_id>",
 			}},
 		},
-		// TODO: Add test cases.
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			i, err := id.NewObjectId(tt.in)
+
+			if tt.err != nil {
+				require.ErrorIs(t, err, tt.err)
+				return
+			}
+
+			require.NoError(t, err)
+			require.Equal(t, tt.result, i)
+			if tt.out == "" {
+				require.Equal(t, tt.in, i.String())
+			} else {
+				require.Equal(t, tt.out, i.String())
+			}
+		})
+	}
+}
+
+func Test_SchemaId(t *testing.T) {
+
+	tests := []struct {
+		name   string
+		in     any
+		out    string
+		result *id.ObjectId
+		err    error
+	}{
+		{
+			name: "valid string",
+			in:   "/spaces/<space_id>/envs/<env_id>/schema/<collection_id>",
+			result: &id.ObjectId{Descriptor: &id.SchemaId{
+				EnvironmentId: id.EnvironmentId{SpaceId: id.SpaceId{SpaceID: "<space_id>"}, EnvironmentID: "<env_id>"},
+				CollectionID:  "<collection_id>",
+			}},
+		},
+		{
+			name: "valid map",
+			in:   map[string]any{"type": "schema", "space_id": "<space_id>", "env_id": "<env_id>", "col_id": "<collection_id>"},
+			out:  "/spaces/<space_id>/envs/<env_id>/schema/<collection_id>",
+			result: &id.ObjectId{Descriptor: &id.SchemaId{
+				EnvironmentId: id.EnvironmentId{SpaceId: id.SpaceId{SpaceID: "<space_id>"}, EnvironmentID: "<env_id>"},
+				CollectionID:  "<collection_id>",
+			}},
+		},
 	}
 
 	for _, tt := range tests {
@@ -263,7 +646,6 @@ func Test_ItemId(t *testing.T) {
 				ItemID: "<item_id>",
 			}},
 		},
-		// TODO: Add test cases.
 	}
 
 	for _, tt := range tests {
@@ -330,7 +712,72 @@ func Test_FieldId(t *testing.T) {
 				Field: "<field>",
 			}},
 		},
-		// TODO: Add test cases.
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			i, err := id.NewObjectId(tt.in)
+
+			if tt.err != nil {
+				require.ErrorIs(t, err, tt.err)
+				return
+			}
+
+			require.NoError(t, err)
+			require.Equal(t, tt.result, i)
+			if tt.out == "" {
+				require.Equal(t, tt.in, i.String())
+			} else {
+				require.Equal(t, tt.out, i.String())
+			}
+		})
+	}
+}
+
+func Test_RevisionId(t *testing.T) {
+
+	tests := []struct {
+		name   string
+		in     any
+		out    string
+		result *id.ObjectId
+		err    error
+	}{
+		{
+			name: "valid string",
+			in:   "/spaces/<space_id>/envs/<env_id>/cols/<collection_id>/items/<item_id>/revs/<rev_id>",
+			result: &id.ObjectId{Descriptor: &id.RevisionId{
+				ItemId: id.ItemId{
+					CollectionId: id.CollectionId{
+						EnvironmentId: id.EnvironmentId{
+							SpaceId:       id.SpaceId{SpaceID: "<space_id>"},
+							EnvironmentID: "<env_id>",
+						},
+						CollectionID: "<collection_id>",
+					},
+					ItemID: "<item_id>",
+				},
+				RevisionID: "<rev_id>",
+			}},
+		},
+		{
+			name: "valid map",
+			in:   map[string]any{"type": "revision", "space_id": "<space_id>", "env_id": "<env_id>", "col_id": "<collection_id>", "item_id": "<item_id>", "rev_id": "<rev_id>"},
+			out:  "/spaces/<space_id>/envs/<env_id>/cols/<collection_id>/items/<item_id>/revs/<rev_id>",
+			result: &id.ObjectId{Descriptor: &id.RevisionId{
+				ItemId: id.ItemId{
+					CollectionId: id.CollectionId{
+						EnvironmentId: id.EnvironmentId{
+							SpaceId:       id.SpaceId{SpaceID: "<space_id>"},
+							EnvironmentID: "<env_id>",
+						},
+						CollectionID: "<collection_id>",
+					},
+					ItemID: "<item_id>",
+				},
+				RevisionID: "<rev_id>",
+			}},
+		},
 	}
 
 	for _, tt := range tests {
diff --git a/id/user.go b/id/user.go
index ab8ddfa26d30fd720d137f0e56588061590f3a0e..8b4100b01039f5ebd65722e2521645304df31b04 100644
--- a/id/user.go
+++ b/id/user.go
@@ -1,6 +1,10 @@
 package id
 
-import "fmt"
+import (
+	"fmt"
+
+	"git.perx.ru/perxis/perxis-go/pkg/users"
+)
 
 const (
 	User        = "user"
@@ -25,7 +29,7 @@ func (id *UserId) String() string {
 
 func (id *UserId) FromParts(parts []string) error {
 	if len(parts) != 2 || parts[0] != UsersPrefix {
-		return ErrInvalid
+		return ErrInvalidID
 	}
 	id.UserID = parts[1]
 	return nil
@@ -41,14 +45,18 @@ func (id *UserId) Map() map[string]any {
 func (id *UserId) FromMap(m map[string]any) error {
 	id.UserID, _ = m["user_id"].(string)
 	if id.UserID == "" {
-		return fmt.Errorf("%w: UserId required", ErrInvalid)
+		return fmt.Errorf("%w: UserId required", ErrInvalidID)
 	}
 	return nil
 }
 
 func (id *UserId) Validate() error {
 	if id.UserID == "" {
-		return fmt.Errorf("%w: UserId required", ErrInvalid)
+		return fmt.Errorf("%w: UserId required", ErrInvalidID)
 	}
 	return nil
 }
+
+func NewUserId(u users.User) *ObjectId {
+	return &ObjectId{Descriptor: &UserId{UserID: u.ID}}
+}