diff --git a/pkg/extension/schema.go b/pkg/extension/schema.go
index cf71a4568c8ed734bda41e344936b728a8ed8b99..1e44488e0918776fbe770f52b333bba8828317e8 100644
--- a/pkg/extension/schema.go
+++ b/pkg/extension/schema.go
@@ -22,7 +22,7 @@ const (
 // NewActionsCollection - создает коллекцию для хранения действий расширений в пространстве
 func NewActionsCollection(spaceID, envID string) *collections.Collection {
 	sch := schema.New(
-		"extension", field.String(validate.Required()).SetTitle("Расширение").SetTextSearch(true),
+		"extension", field.String().SetTitle("Расширение"),
 		"action", field.String(validate.Required()).SetTitle("Действия").SetTextSearch(true),
 		"target", field.Number(
 			field.NumberFormatInt,
@@ -94,15 +94,17 @@ func NewActionsCollection(spaceID, envID string) *collections.Collection {
 }
 
 func getEnumOpt(opts map[int32]string) []validate.EnumOpt {
-	keys := make([]string, 0, len(opts))
-	for _, k := range opts {
+	keys := make([]int32, 0, len(opts))
+	for k := range opts {
 		keys = append(keys, k)
 	}
-	sort.Strings(keys)
+	sort.Slice(keys, func(i, j int) bool {
+		return keys[i] < keys[j]
+	})
 
 	enum := make([]validate.EnumOpt, len(opts))
 	for i, n := range keys {
-		enum[i] = validate.EnumOpt{Name: n, Value: float64(i)}
+		enum[i] = validate.EnumOpt{Name: opts[n], Value: float64(n)}
 	}
 	return enum
 }
diff --git a/pkg/extension/schema_test.go b/pkg/extension/schema_test.go
index b15a210045b85ef7349cbdaad3b7365eb6c411a0..7d33a4b5ef724ad2e2a9dc98723b39f8139a46b2 100644
--- a/pkg/extension/schema_test.go
+++ b/pkg/extension/schema_test.go
@@ -17,10 +17,10 @@ func Test_getEnumOpt(t *testing.T) {
 			name: "#1",
 			opts: map[int32]string{1: "a", 2: "b", 3: "c", 1000: "w"},
 			want: []validate.EnumOpt{
-				{Name: "a", Value: float64(0)},
-				{Name: "b", Value: float64(1)},
-				{Name: "c", Value: float64(2)},
-				{Name: "w", Value: float64(3)},
+				{Name: "a", Value: float64(1)},
+				{Name: "b", Value: float64(2)},
+				{Name: "c", Value: float64(3)},
+				{Name: "w", Value: float64(1000)},
 			},
 		},
 	}
diff --git a/pkg/extension/server.go b/pkg/extension/server.go
index 4e3c4fc2817869a32159cece4fb90706d3bbd36a..4ddb3143008efaeaaf70b5c74042feaece95b5df 100644
--- a/pkg/extension/server.go
+++ b/pkg/extension/server.go
@@ -73,6 +73,12 @@ func SingleExtension(extension Extension) ServerOption {
 	}
 }
 
+func WithRouteFn(fn RouteFn) ServerOption {
+	return func(c *Server) {
+		c.extensions = fn
+	}
+}
+
 type Server struct {
 	extensions RouteFn
 	wrapErr    WrapErrFn
diff --git a/pkg/schema/walk/fn.go b/pkg/schema/walk/fn.go
index c3eaf35c569c18ba8ead7c7ff48c08d03f2a9d90..9b1d4f22316cf37cae1af824d98f611b7dc0bcf7 100644
--- a/pkg/schema/walk/fn.go
+++ b/pkg/schema/walk/fn.go
@@ -1,10 +1,15 @@
 package walk
 
+import "reflect"
+
 func GenericMerge(c *WalkContext) (err error) {
 	return
 }
 
 func KeepSrc(c *WalkContext) (err error) {
+	if reflect.DeepEqual(c.Src, c.Dst) {
+		return
+	}
 	c.Dst = c.Src
 	c.Changed = true
 	return
diff --git a/pkg/schema/walk/walk_test.go b/pkg/schema/walk/walk_test.go
index e20adb462735e83c92c8b04f5c159e336e49f2b0..3fd01bd577c3fe16abb1cae7b2e9785e0edc659c 100644
--- a/pkg/schema/walk/walk_test.go
+++ b/pkg/schema/walk/walk_test.go
@@ -46,6 +46,54 @@ func TestWalker_DataWalk(t *testing.T) {
 		wantErr     bool
 	}{
 		{"generic",
+			&WalkConfig{
+				Fields: map[string]FieldConfig{},
+			},
+			map[string]interface{}{
+				"a": "src_a",
+				"b": "src_b",
+				"obj1": map[string]interface{}{
+					"a": "src_obj1_a",
+					"b": "src_obj1_b",
+					"obj2": map[string]interface{}{
+						"a": "dst_obj1_obj2_a",
+					},
+					"obj3": map[string]interface{}{
+						"e": "dst_obj1_obj3_e",
+					},
+				},
+				"inline_str_1": "src_inline_1",
+				"inline_str_2": "src_inline_2",
+				"slice":        []interface{}{"src_s1", "src_s2"},
+			},
+			map[string]interface{}{
+				"a":                 "dst_a",
+				"field_not_extists": "remove",
+				"obj1": map[string]interface{}{
+					"a": "dst_obj1_a",
+					"obj2": map[string]interface{}{
+						"a": "dst_obj1_obj2_a",
+					},
+				},
+				"inline_str_1": "dst_inline_1",
+				"inline_str_2": "dst_inline_2",
+				"slice":        []interface{}{"dst_s1", "dst_s2", "dst_s3"},
+			},
+			map[string]interface{}{
+				"a": "dst_a",
+				"obj1": map[string]interface{}{
+					"a": "dst_obj1_a",
+					"obj2": map[string]interface{}{
+						"a": "dst_obj1_obj2_a",
+					},
+				},
+				"inline_str_1": "dst_inline_1",
+				"inline_str_2": "dst_inline_2",
+				"slice":        []interface{}{"dst_s1", "dst_s2", "dst_s3"},
+			},
+			false, false,
+		},
+		{"keep src changed",
 			&WalkConfig{
 				Fields: map[string]FieldConfig{
 					"obj1.a":       {Fn: KeepSrc},
@@ -96,6 +144,68 @@ func TestWalker_DataWalk(t *testing.T) {
 				"inline_str_2": "src_inline_2",
 				"slice":        []interface{}{"dst_s1", "src_s2", "dst_s3"},
 			},
+			true, false,
+		},
+		{"keep src not changed",
+			&WalkConfig{
+				Fields: map[string]FieldConfig{
+					"obj1.a":       {Fn: KeepSrc},
+					"slice.1":      {Fn: KeepSrc},
+					"inline_str_1": {Fn: KeepSrc},
+					"inline_str_2": {Fn: KeepSrc},
+				},
+			},
+			map[string]interface{}{
+				"a": "src_a",
+				"b": "src_b",
+				"obj1": map[string]interface{}{
+					"a": "src_obj1_a",
+					"b": "src_obj1_b",
+					"obj2": map[string]interface{}{
+						"a": "dst_obj1_obj2_a",
+					},
+					"obj3": map[string]interface{}{
+						"e": "dst_obj1_obj3_e",
+					},
+				},
+				"inline_str_1": "src_inline_1",
+				"inline_str_2": "src_inline_2",
+				"slice":        []interface{}{"src_s1", "src_s2"},
+			},
+			map[string]interface{}{
+				"a": "src_a",
+				"b": "src_b",
+				"obj1": map[string]interface{}{
+					"a": "src_obj1_a",
+					"b": "src_obj1_b",
+					"obj2": map[string]interface{}{
+						"a": "dst_obj1_obj2_a",
+					},
+					"obj3": map[string]interface{}{
+						"e": "dst_obj1_obj3_e",
+					},
+				},
+				"inline_str_1": "src_inline_1",
+				"inline_str_2": "src_inline_2",
+				"slice":        []interface{}{"src_s1", "src_s2"},
+			},
+			map[string]interface{}{
+				"a": "src_a",
+				"b": "src_b",
+				"obj1": map[string]interface{}{
+					"a": "src_obj1_a",
+					"b": "src_obj1_b",
+					"obj2": map[string]interface{}{
+						"a": "dst_obj1_obj2_a",
+					},
+					"obj3": map[string]interface{}{
+						"e": "dst_obj1_obj3_e",
+					},
+				},
+				"inline_str_1": "src_inline_1",
+				"inline_str_2": "src_inline_2",
+				"slice":        []interface{}{"src_s1", "src_s2"},
+			},
 			false, false,
 		},
 	}
@@ -103,11 +213,12 @@ func TestWalker_DataWalk(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			m := NewWalker(s, tt.config)
 			dst := tt.dst
-			res, _, err := m.DataWalk(context.Background(), dst, tt.src)
-			assert.Equal(t, tt.res, res)
+			res, chg, err := m.DataWalk(context.Background(), dst, tt.src)
 			if tt.wantErr {
 				require.Error(t, err)
 			} else {
+				assert.Equal(t, tt.res, res)
+				assert.Equal(t, tt.wantChanged, chg)
 				require.NoError(t, err)
 			}
 		})