From 89f0646f74393f6374a24310507bca8eabe61465 Mon Sep 17 00:00:00 2001
From: Ghost User <ghost@example.com>
Date: Thu, 2 Jan 2025 08:34:09 +0000
Subject: [PATCH 01/79] [renovate] Update module golang.org/x/net to v0.32.0

See merge request danet/gosdn!1125

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 4 ++--
 go.sum | 4 ++++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/go.mod b/go.mod
index 2879fe711..15aaf3ba0 100644
--- a/go.mod
+++ b/go.mod
@@ -77,8 +77,8 @@ require (
 	github.com/xdg-go/stringprep v1.0.4 // indirect
 	github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
 	github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
-	golang.org/x/crypto v0.30.0
-	golang.org/x/net v0.31.0
+	golang.org/x/crypto v0.31.0
+	golang.org/x/net v0.33.0
 	golang.org/x/sys v0.28.0 // indirect
 	golang.org/x/term v0.27.0 // indirect
 	golang.org/x/text v0.21.0 // indirect
diff --git a/go.sum b/go.sum
index 880acc9d1..192ef1d3f 100644
--- a/go.sum
+++ b/go.sum
@@ -411,6 +411,8 @@ golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
 golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
 golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY=
 golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
+golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
+golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7 h1:wDLEX9a7YQoKdKNQt88rtydkqDxeGaBUTnIYc3iG/mA=
 golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
@@ -446,6 +448,8 @@ golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
 golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
 golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
 golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
+golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
+golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-- 
GitLab


From 078238f236244c68183e92b03d71ae976ac9f463 Mon Sep 17 00:00:00 2001
From: Ghost User <ghost@example.com>
Date: Thu, 2 Jan 2025 08:43:17 +0000
Subject: [PATCH 02/79] [renovate] Update renovate/renovate Docker tag to
 v39.60.0

See merge request danet/gosdn!1127

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 .gitlab/ci/.renovate.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab/ci/.renovate.yml b/.gitlab/ci/.renovate.yml
index 55c8ea335..5faf72ffd 100644
--- a/.gitlab/ci/.renovate.yml
+++ b/.gitlab/ci/.renovate.yml
@@ -1,7 +1,7 @@
 renovate:
     stage: tools
 
-    image: renovate/renovate:39.48.1
+    image: renovate/renovate:39.87.0
 
     variables:
         LOG_LEVEL: debug
-- 
GitLab


From a1fd8bda7ff49de285e42ae0e0c575e54e5b2161 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Thu, 2 Jan 2025 08:56:41 +0000
Subject: [PATCH 03/79] [renovate] Update module google.golang.org/grpc to
 v1.69.2

See merge request danet/gosdn!1132

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 2 +-
 go.sum | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/go.mod b/go.mod
index 15aaf3ba0..6aeeb8613 100644
--- a/go.mod
+++ b/go.mod
@@ -24,7 +24,7 @@ require (
 	github.com/stretchr/testify v1.10.0
 	go.mongodb.org/mongo-driver v1.17.1
 	golang.org/x/sync v0.10.0
-	google.golang.org/grpc v1.68.1
+	google.golang.org/grpc v1.69.2
 	google.golang.org/protobuf v1.35.2
 	gopkg.in/yaml.v3 v3.0.1
 )
diff --git a/go.sum b/go.sum
index 192ef1d3f..187503b7b 100644
--- a/go.sum
+++ b/go.sum
@@ -617,6 +617,8 @@ google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0=
 google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA=
 google.golang.org/grpc v1.68.1 h1:oI5oTa11+ng8r8XMMN7jAOmWfPZWbYpCFaMUTACxkM0=
 google.golang.org/grpc v1.68.1/go.mod h1:+q1XYFJjShcqn0QZHvCyeR4CXPA+llXIeUIfIe00waw=
+google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU=
+google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
-- 
GitLab


From c97021c2269817af40b0a8b7cd60aac952a8b202 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Thu, 2 Jan 2025 09:07:42 +0000
Subject: [PATCH 04/79] [renovate] Update module github.com/openconfig/gnmi to
 v0.12.0

See merge request danet/gosdn!1133

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 4 ++--
 go.sum | 4 ++++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/go.mod b/go.mod
index 6aeeb8613..d0adaae95 100644
--- a/go.mod
+++ b/go.mod
@@ -10,7 +10,7 @@ require (
 	github.com/google/uuid v1.6.0
 	github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0
 	github.com/mitchellh/go-homedir v1.1.0
-	github.com/openconfig/gnmi v0.11.0
+	github.com/openconfig/gnmi v0.12.0
 	github.com/openconfig/goyang v1.6.0
 	github.com/openconfig/ygot v0.29.20
 	github.com/prometheus/client_golang v1.20.5
@@ -122,7 +122,7 @@ require (
 	github.com/stoewer/go-strcase v1.3.0 // indirect
 	go.uber.org/atomic v1.9.0 // indirect
 	go.uber.org/multierr v1.9.0 // indirect
-	golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7 // indirect
+	golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
 	google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 // indirect
 	gotest.tools/v3 v3.5.1 // indirect
 )
diff --git a/go.sum b/go.sum
index 187503b7b..6b8f0e621 100644
--- a/go.sum
+++ b/go.sum
@@ -262,6 +262,8 @@ github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DV
 github.com/openconfig/gnmi v0.10.0/go.mod h1:Y9os75GmSkhHw2wX8sMsxfI7qRGAEcDh8NTa5a8vj6E=
 github.com/openconfig/gnmi v0.11.0 h1:H7pLIb/o3xObu3+x0Fv9DCK7TH3FUh7mNwbYe+34hFw=
 github.com/openconfig/gnmi v0.11.0/go.mod h1:9oJSQPPCpNvfMRj8e4ZoLVAw4wL8HyxXbiDlyuexCGU=
+github.com/openconfig/gnmi v0.12.0 h1:aPkmcX9pdcz6QqsBsXXg5UQooqhnmlHD3JtdtvtzmaU=
+github.com/openconfig/gnmi v0.12.0/go.mod h1:5a/cIOZevJLfJgd1qWkgYROE8xfgEbaSJXpdD8xk/LQ=
 github.com/openconfig/goyang v0.0.0-20200115183954-d0a48929f0ea/go.mod h1:dhXaV0JgHJzdrHi2l+w0fZrwArtXL7jEFoiqLEdmkvU=
 github.com/openconfig/goyang v1.6.0 h1:JjnPbLY1/y28VyTO67LsEV0TaLWNiZyDcsppGq4F4is=
 github.com/openconfig/goyang v1.6.0/go.mod h1:sdNZi/wdTZyLNBNfgLzmmbi7kISm7FskMDKKzMY+x1M=
@@ -416,6 +418,8 @@ golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ss
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7 h1:wDLEX9a7YQoKdKNQt88rtydkqDxeGaBUTnIYc3iG/mA=
 golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
+golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
+golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-- 
GitLab


From 2b36e705948a4af7477509f438ebec55ee1b847d Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Thu, 2 Jan 2025 09:22:54 +0000
Subject: [PATCH 05/79] [renovate] Update golangci/golangci-lint Docker tag to
 v1.63.1

See merge request danet/gosdn!1137

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 .gitlab/ci/.code-quality-ci.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab/ci/.code-quality-ci.yml b/.gitlab/ci/.code-quality-ci.yml
index d054508c4..56ee84f2e 100644
--- a/.gitlab/ci/.code-quality-ci.yml
+++ b/.gitlab/ci/.code-quality-ci.yml
@@ -1,5 +1,5 @@
 code-quality:
-    image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/golangci/golangci-lint:v1.62.2-alpine
+    image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/golangci/golangci-lint:v1.63.1-alpine
     stage: analyze
     script:
         # writes golangci-lint output to gl-code-quality-report.json
-- 
GitLab


From 479b5c6811bcd54739da94c475531b7d2f95644d Mon Sep 17 00:00:00 2001
From: Ghost User <ghost@example.com>
Date: Fri, 3 Jan 2025 07:48:03 +0000
Subject: [PATCH 06/79] [renovate] Update
 google.golang.org/genproto/googleapis/api digest to e6fa225

See merge request danet/gosdn!1126

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 6 +++---
 go.sum | 6 ++++++
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/go.mod b/go.mod
index d0adaae95..5e246227c 100644
--- a/go.mod
+++ b/go.mod
@@ -25,7 +25,7 @@ require (
 	go.mongodb.org/mongo-driver v1.17.1
 	golang.org/x/sync v0.10.0
 	google.golang.org/grpc v1.69.2
-	google.golang.org/protobuf v1.35.2
+	google.golang.org/protobuf v1.36.1
 	gopkg.in/yaml.v3 v3.0.1
 )
 
@@ -91,7 +91,7 @@ require (
 	github.com/hashicorp/go-multierror v1.1.1
 	github.com/hashicorp/go-plugin v1.4.10
 	github.com/lesismal/nbio v1.5.12
-	google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a
+	google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d
 )
 
 require (
@@ -123,6 +123,6 @@ require (
 	go.uber.org/atomic v1.9.0 // indirect
 	go.uber.org/multierr v1.9.0 // indirect
 	golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
-	google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect
 	gotest.tools/v3 v3.5.1 // indirect
 )
diff --git a/go.sum b/go.sum
index 6b8f0e621..f71564f8d 100644
--- a/go.sum
+++ b/go.sum
@@ -583,6 +583,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697 h1:
 google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697/go.mod h1:+D9ySVjN8nY8YCVjc5O7PZDIdZporIDY3KaGfJunh88=
 google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a h1:OAiGFfOiA0v9MRYsSidp3ubZaBnteRUyn3xB2ZQ5G/E=
 google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a/go.mod h1:jehYqy3+AhJU9ve55aNOaSml7wUXjF9x6z2LcCfpAhY=
+google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d h1:H8tOf8XM88HvKqLTxe755haY6r1fqqzLbEnfrmLXlSA=
+google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d/go.mod h1:2v7Z7gP2ZUOGsaFyxATQSRoBnKygqVq2Cwnvom7QiqY=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed h1:J6izYgfBXAI3xTKLgxzTmUltdYaLsuBxFCgDHWJ/eXg=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
@@ -603,6 +605,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f h1:
 google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 h1:LWZqQOEjDyONlF1H6afSWpAL/znlREo2tHfLoe+8LMA=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1:TqExAhdPaB60Ux47Cn0oLV07rGnxZzIsaRhQaqS666A=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
@@ -643,6 +647,8 @@ google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFyt
 google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
 google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
+google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
-- 
GitLab


From a0f745dacb2690efb194b4b25ce5d51bd3c71be2 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Fri, 3 Jan 2025 07:56:49 +0000
Subject: [PATCH 07/79] [renovate] Update module
 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go to
 v1.36.1-20241127180247-a33202765966.1

See merge request danet/gosdn!1134

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 2 +-
 go.sum | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/go.mod b/go.mod
index 5e246227c..9125b3bc1 100644
--- a/go.mod
+++ b/go.mod
@@ -86,7 +86,7 @@ require (
 )
 
 require (
-	buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20241127180247-a33202765966.1
+	buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.1-20241127180247-a33202765966.1
 	github.com/bufbuild/protovalidate-go v0.7.3
 	github.com/hashicorp/go-multierror v1.1.1
 	github.com/hashicorp/go-plugin v1.4.10
diff --git a/go.sum b/go.sum
index f71564f8d..3344b045b 100644
--- a/go.sum
+++ b/go.sum
@@ -16,6 +16,8 @@ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-2024092016423
 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20240920164238-5a7b106cbb87.1/go.mod h1:mnHCFccv4HwuIAOHNGdiIc5ZYbBCvbTWZcodLN5wITI=
 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20241127180247-a33202765966.1 h1:jLd96rDDNJ+zIJxvV/L855VEtrjR0G4aePVDlCpf6kw=
 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20241127180247-a33202765966.1/go.mod h1:mnHCFccv4HwuIAOHNGdiIc5ZYbBCvbTWZcodLN5wITI=
+buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.1-20241127180247-a33202765966.1 h1:v223wh/bhlSHSc0tU9PXRWXHhkw3UWMtth7TmYGfHAQ=
+buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.1-20241127180247-a33202765966.1/go.mod h1:/zlFuuECgFgewxwW6qQKgvMJ07YZkWlVkcSxEhJprJw=
 cel.dev/expr v0.18.0 h1:CJ6drgk+Hf96lkLikr4rFf19WrU0BOWEihyZnI2TAzo=
 cel.dev/expr v0.18.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-- 
GitLab


From face532ae93d3d850dc6f7b65ad69fc450334cf9 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Fri, 3 Jan 2025 08:08:45 +0000
Subject: [PATCH 08/79] [renovate] Update golangci/golangci-lint Docker tag to
 v1.63.3

See merge request danet/gosdn!1138

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 .gitlab/ci/.code-quality-ci.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab/ci/.code-quality-ci.yml b/.gitlab/ci/.code-quality-ci.yml
index 56ee84f2e..1273f2e07 100644
--- a/.gitlab/ci/.code-quality-ci.yml
+++ b/.gitlab/ci/.code-quality-ci.yml
@@ -1,5 +1,5 @@
 code-quality:
-    image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/golangci/golangci-lint:v1.63.1-alpine
+    image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/golangci/golangci-lint:v1.63.3-alpine
     stage: analyze
     script:
         # writes golangci-lint output to gl-code-quality-report.json
-- 
GitLab


From 3215297beae2b1b5ce1db347de6ce9cfcec288ce Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Fri, 3 Jan 2025 08:20:19 +0000
Subject: [PATCH 09/79] [renovate] Update renovate/renovate Docker tag to
 v39.90.1

See merge request danet/gosdn!1139

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 .gitlab/ci/.renovate.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab/ci/.renovate.yml b/.gitlab/ci/.renovate.yml
index 5faf72ffd..fe2b9ce8c 100644
--- a/.gitlab/ci/.renovate.yml
+++ b/.gitlab/ci/.renovate.yml
@@ -1,7 +1,7 @@
 renovate:
     stage: tools
 
-    image: renovate/renovate:39.87.0
+    image: renovate/renovate:39.90.1
 
     variables:
         LOG_LEVEL: debug
-- 
GitLab


From 5d7d372fb64d72ea69d672564ca2b1c95e62b853 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Mon, 6 Jan 2025 07:48:48 +0000
Subject: [PATCH 10/79] [renovate] Update module
 github.com/grpc-ecosystem/grpc-gateway/v2 to v2.25.1

See merge request danet/gosdn!1136

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 2 +-
 go.sum | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/go.mod b/go.mod
index 9125b3bc1..21df761c9 100644
--- a/go.mod
+++ b/go.mod
@@ -8,7 +8,7 @@ require (
 	github.com/docker/docker v24.0.9+incompatible
 	github.com/google/go-cmp v0.6.0
 	github.com/google/uuid v1.6.0
-	github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0
+	github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1
 	github.com/mitchellh/go-homedir v1.1.0
 	github.com/openconfig/gnmi v0.12.0
 	github.com/openconfig/goyang v1.6.0
diff --git a/go.sum b/go.sum
index 3344b045b..0ba985a52 100644
--- a/go.sum
+++ b/go.sum
@@ -171,6 +171,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 h1:ad0vkEBuk23VJzZR9nkLVG0YAoN
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0/go.mod h1:igFoXX2ELCW06bol23DWPB5BEWfZISOzSP5K2sbLea0=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 h1:TmHmbvxPmaegwhDubVz0lICL0J5Ka2vwTzhoePEXsGE=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0/go.mod h1:qztMSjm835F2bXf+5HKAPIS5qsmQDqZna/PgVt4rWtI=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
 github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
 github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
 github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
-- 
GitLab


From 9b886a0e9d538c6d118902ecb4832e280d6e6f4b Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Mon, 6 Jan 2025 08:00:03 +0000
Subject: [PATCH 11/79] [renovate] Update golangci/golangci-lint Docker tag to
 v1.63.4

See merge request danet/gosdn!1141

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 .gitlab/ci/.code-quality-ci.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab/ci/.code-quality-ci.yml b/.gitlab/ci/.code-quality-ci.yml
index 1273f2e07..95ed3abe9 100644
--- a/.gitlab/ci/.code-quality-ci.yml
+++ b/.gitlab/ci/.code-quality-ci.yml
@@ -1,5 +1,5 @@
 code-quality:
-    image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/golangci/golangci-lint:v1.63.3-alpine
+    image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/golangci/golangci-lint:v1.63.4-alpine
     stage: analyze
     script:
         # writes golangci-lint output to gl-code-quality-report.json
-- 
GitLab


From 85456e24c180a7b34a20abdd83f1fd028f6f245f Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Mon, 6 Jan 2025 08:20:28 +0000
Subject: [PATCH 12/79] [renovate] Update renovate/renovate Docker tag to
 v39.91.0

See merge request danet/gosdn!1142

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 .gitlab/ci/.renovate.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab/ci/.renovate.yml b/.gitlab/ci/.renovate.yml
index fe2b9ce8c..57dfa95c0 100644
--- a/.gitlab/ci/.renovate.yml
+++ b/.gitlab/ci/.renovate.yml
@@ -1,7 +1,7 @@
 renovate:
     stage: tools
 
-    image: renovate/renovate:39.90.1
+    image: renovate/renovate:39.91.0
 
     variables:
         LOG_LEVEL: debug
-- 
GitLab


From 45dcefa1e6a3521d5244b86f6698ed56cf13fc4f Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Tue, 7 Jan 2025 07:43:41 +0000
Subject: [PATCH 13/79] [renovate] Update
 google.golang.org/genproto/googleapis/api digest to 5f5ef82

See merge request danet/gosdn!1143

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 4 ++--
 go.sum | 4 ++++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/go.mod b/go.mod
index 21df761c9..6e4cf99a4 100644
--- a/go.mod
+++ b/go.mod
@@ -91,7 +91,7 @@ require (
 	github.com/hashicorp/go-multierror v1.1.1
 	github.com/hashicorp/go-plugin v1.4.10
 	github.com/lesismal/nbio v1.5.12
-	google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d
+	google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422
 )
 
 require (
@@ -123,6 +123,6 @@ require (
 	go.uber.org/atomic v1.9.0 // indirect
 	go.uber.org/multierr v1.9.0 // indirect
 	golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
-	google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d // indirect
 	gotest.tools/v3 v3.5.1 // indirect
 )
diff --git a/go.sum b/go.sum
index 0ba985a52..e7d3f5158 100644
--- a/go.sum
+++ b/go.sum
@@ -589,6 +589,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a h1:
 google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a/go.mod h1:jehYqy3+AhJU9ve55aNOaSml7wUXjF9x6z2LcCfpAhY=
 google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d h1:H8tOf8XM88HvKqLTxe755haY6r1fqqzLbEnfrmLXlSA=
 google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d/go.mod h1:2v7Z7gP2ZUOGsaFyxATQSRoBnKygqVq2Cwnvom7QiqY=
+google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 h1:GVIKPyP/kLIyVOgOnTwFOrvQaQUzOzGMCxgFUOEmm24=
+google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422/go.mod h1:b6h1vNKhxaSoEI+5jc3PJUCustfli/mRab7295pY7rw=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed h1:J6izYgfBXAI3xTKLgxzTmUltdYaLsuBxFCgDHWJ/eXg=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
@@ -611,6 +613,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 h1:
 google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1:TqExAhdPaB60Ux47Cn0oLV07rGnxZzIsaRhQaqS666A=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d h1:xJJRGY7TJcvIlpSrN3K6LAWgNFUILlO+OMAqtg9aqnw=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
-- 
GitLab


From 11a1f3f00d3b4de9213b33c855189b63fcf480e8 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Tue, 7 Jan 2025 07:55:01 +0000
Subject: [PATCH 14/79] [renovate] Update renovate/renovate Docker tag to
 v39.91.3

See merge request danet/gosdn!1144

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 .gitlab/ci/.renovate.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab/ci/.renovate.yml b/.gitlab/ci/.renovate.yml
index 57dfa95c0..03f8fddfa 100644
--- a/.gitlab/ci/.renovate.yml
+++ b/.gitlab/ci/.renovate.yml
@@ -1,7 +1,7 @@
 renovate:
     stage: tools
 
-    image: renovate/renovate:39.91.0
+    image: renovate/renovate:39.91.3
 
     variables:
         LOG_LEVEL: debug
-- 
GitLab


From 04893c56040c397ba3004ae21c5fb74ae60aef3c Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@@stud.h-da.de>
Date: Tue, 7 Jan 2025 11:37:12 +0100
Subject: [PATCH 15/79] add react ui to containerlab

---
 .gitlab/ci/.build-binaries.yml                    |  1 +
 .gitlab/ci/.build-container-images.yml            | 10 ++++++++++
 .gitlab/ci/.react-ui.yml                          |  3 ---
 Makefile                                          |  2 +-
 dev_env_data/clab/gosdn_slim.clab.yaml            |  7 +++++++
 .../docker-compose/basic_docker-compose.yml       |  5 +++++
 makefiles/container/Makefile                      |  3 +++
 plugin-registry/plugin-registry.Dockerfile        |  7 ++++---
 react-ui/.dockerignore                            |  5 +++++
 react-ui/docker/webserver/Dockerfile              | 15 ++++++++++++---
 react-ui/docker/webserver/nginx.conf              |  1 -
 react-ui/scripts/build.sh                         |  2 +-
 react-ui/vite.config.mjs                          |  3 ++-
 13 files changed, 51 insertions(+), 13 deletions(-)
 delete mode 100644 .gitlab/ci/.react-ui.yml
 create mode 100644 react-ui/.dockerignore

diff --git a/.gitlab/ci/.build-binaries.yml b/.gitlab/ci/.build-binaries.yml
index 174203fdc..4877cd169 100644
--- a/.gitlab/ci/.build-binaries.yml
+++ b/.gitlab/ci/.build-binaries.yml
@@ -16,5 +16,6 @@ build-all-binaries:
           - artifacts/venv-manager
           - artifacts/inventory-manager
           - artifacts/plugin-registry
+          - artifacts/react-ui
         expire_in: 1 week
     <<: *build-binaries
diff --git a/.gitlab/ci/.build-container-images.yml b/.gitlab/ci/.build-container-images.yml
index da70dcba2..79e22bc63 100644
--- a/.gitlab/ci/.build-container-images.yml
+++ b/.gitlab/ci/.build-container-images.yml
@@ -75,6 +75,16 @@ build-inventory-manager-image:
         - docker push "$INVENTORY_MANAGER_IMAGE_NAME:$CI_COMMIT_REF_SLUG"
     <<: *build
 
+build-react-ui-image:
+    script:
+        - REACT_UI_IMAGE_NAME="${CI_REGISTRY_IMAGE}/react-ui"
+        - docker buildx build -t "$REACT_UI_IMAGE_NAME:$CI_COMMIT_SHA" -f "${CI_PROJECT_DIR}/react-ui/docker/webserver/Dockerfile" ./react-ui
+        - docker push "$REACT_UI_IMAGE_NAME:$CI_COMMIT_SHA"
+        - docker tag "$REACT_UI_IMAGE_NAME:$CI_COMMIT_SHA" "$REACT_UI_IMAGE_NAME:$CI_COMMIT_REF_SLUG"
+        - docker push "$REACT_UI_IMAGE_NAME:$CI_COMMIT_REF_SLUG"
+    <<: *build
+    
+
 build-integration-test-images:
     needs: ["build-controller-image"]
     script:
diff --git a/.gitlab/ci/.react-ui.yml b/.gitlab/ci/.react-ui.yml
deleted file mode 100644
index 873b694c8..000000000
--- a/.gitlab/ci/.react-ui.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-build-react-ui:
-  stage: build
-  
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 888644abe..73ae77b6a 100644
--- a/Makefile
+++ b/Makefile
@@ -60,7 +60,7 @@ lint-fix: install-tools
 
 build: pre build-gosdn build-gosdnc build-plugin-registry build-venv-manager build-arista-routing-engine-app build-hostname-checker-app build-basic-interface-monitoring-app build-inventory-manager
 
-containerize-all: containerize-gosdn containerize-gosdnc containerize-plugin-registry containerize-venv-manager containerize-arista-routing-engine-app containerize-inventory-manager
+containerize-all: containerize-gosdn containerize-gosdnc containerize-plugin-registry containerize-venv-manager containerize-arista-routing-engine-app containerize-inventory-manager containerize-react-ui
 
 generate-all-certs: pre generate-root-ca generate-gosdn-certs generate-gnmi-target-certs
 
diff --git a/dev_env_data/clab/gosdn_slim.clab.yaml b/dev_env_data/clab/gosdn_slim.clab.yaml
index f4d76846c..b3ef8eb08 100644
--- a/dev_env_data/clab/gosdn_slim.clab.yaml
+++ b/dev_env_data/clab/gosdn_slim.clab.yaml
@@ -13,6 +13,13 @@ topology:
       image: plugin-registry
       mgmt-ipv4: 172.100.0.16
 
+    react-ui:
+      kind: linux
+      image: react-ui
+      ports:
+        - 127.0.0.1:8088:80
+      mgmt-ipv4: 172.100.0.6
+
     gosdn:
       kind: linux
       image: gosdn
diff --git a/dev_env_data/docker-compose/basic_docker-compose.yml b/dev_env_data/docker-compose/basic_docker-compose.yml
index 4e7664161..2544e7b0f 100644
--- a/dev_env_data/docker-compose/basic_docker-compose.yml
+++ b/dev_env_data/docker-compose/basic_docker-compose.yml
@@ -75,5 +75,10 @@ services:
     command:
       start --cert /etc/gnmi-target/ssl/certs/gnmi-target-selfsigned.crt --key /etc/gnmi-target/ssl/private/gnmi-target-selfsigned.key --ca_file /etc/gnmi-target/ssl/ca.crt
 
+  react-ui:
+    image: react-ui
+    ports:
+      - 127.0.0.1:8088:80
+
 volumes:
     mongo-db-basic:
diff --git a/makefiles/container/Makefile b/makefiles/container/Makefile
index c9c21b972..6e3b97242 100644
--- a/makefiles/container/Makefile
+++ b/makefiles/container/Makefile
@@ -25,3 +25,6 @@ containerize-ws-events-app:
 
 containerize-inventory-manager:
 	docker buildx build --rm -t venv-manager --load -f applications/inventory-manager/inventory-manager.Dockerfile .
+
+containerize-react-ui:
+	docker buildx build --rm --load -t react-ui -f react-ui/docker/webserver/Dockerfile .
diff --git a/plugin-registry/plugin-registry.Dockerfile b/plugin-registry/plugin-registry.Dockerfile
index 05d3aad83..292a134fd 100644
--- a/plugin-registry/plugin-registry.Dockerfile
+++ b/plugin-registry/plugin-registry.Dockerfile
@@ -4,8 +4,9 @@ ARG GITLAB_PROXY
 
 FROM ${GITLAB_PROXY}golang:$GOLANG_VERSION-bookworm as builder
 WORKDIR /plugin-registry/
-RUN apt-get update
-RUN apt-get -y install --no-install-recommends zip
+RUN apt-get update && \
+    apt-get -y install --no-install-recommends zip && \
+    rm -rf /var/lib/apt/lists/*
 COPY . .
 RUN --mount=type=cache,target=/root/go/pkg/mod \
     --mount=type=cache,target=/root/.cache/go-build \
@@ -21,4 +22,4 @@ WORKDIR /app/
 COPY --from=builder /plugin-registry/artifacts/plugin-registry .
 COPY --from=builder /plugin-registry/plugin-registry/plugins ./plugins
 COPY --from=builder /plugin-registry/dev_env_data/plugin-registry/plugin-store.json ./plugin-store.json
-ENTRYPOINT ["./plugin-registry", "-socket", "55057"]
+ENTRYPOINT ["./plugin-registry", "-socket", "55057"]
\ No newline at end of file
diff --git a/react-ui/.dockerignore b/react-ui/.dockerignore
new file mode 100644
index 000000000..5ecec0472
--- /dev/null
+++ b/react-ui/.dockerignore
@@ -0,0 +1,5 @@
+node_modules/
+dist/
+vite/
+tmp/
+.vscode/
\ No newline at end of file
diff --git a/react-ui/docker/webserver/Dockerfile b/react-ui/docker/webserver/Dockerfile
index f4644ee10..71127c09b 100644
--- a/react-ui/docker/webserver/Dockerfile
+++ b/react-ui/docker/webserver/Dockerfile
@@ -1,4 +1,13 @@
-FROM nginx:alpine3.20
+FROM node:alpine3.20 as builder
+
+COPY  ./api/openapiv2/gosdn_northbound.swagger.json /app/api/openapiv2/gosdn_northbound.swagger.json
+COPY ./react-ui /app/react-ui
+
+RUN cd /app/react-ui && yarn && yarn build
 
-COPY dist /usr/share/nginx/html
-COPY docker/webserver/nginx.conf /etc/nginx/nginx.conf 
\ No newline at end of file
+
+# webserver
+FROM nginx:alpine3.20
+COPY --from=builder /app/react-ui/dist /usr/share/nginx/html
+COPY --from=builder /app/react-ui/docker/webserver/nginx.conf /etc/nginx/nginx.conf 
+EXPOSE 80
\ No newline at end of file
diff --git a/react-ui/docker/webserver/nginx.conf b/react-ui/docker/webserver/nginx.conf
index 87066f6ab..eb4fc2be9 100644
--- a/react-ui/docker/webserver/nginx.conf
+++ b/react-ui/docker/webserver/nginx.conf
@@ -41,7 +41,6 @@ http {
 
         #access_log  logs/host.access.log  main;
 
-
         location ^~ /api/ {
             proxy_set_header Host $host;
             proxy_set_header X-Real-IP $remote_addr;
diff --git a/react-ui/scripts/build.sh b/react-ui/scripts/build.sh
index ad0f0cd0b..fb6cb2a21 100755
--- a/react-ui/scripts/build.sh
+++ b/react-ui/scripts/build.sh
@@ -7,7 +7,7 @@ docker run --rm \
     -w /app \
     -u $(id -u):$(id -g) \
     $IMAGE \
-    yarn install && yarn build
+    yarn && yarn build
 
 if [ $? -ne 0 ]; then
     echo "Error while building frontend app"
diff --git a/react-ui/vite.config.mjs b/react-ui/vite.config.mjs
index fefafe05a..fc4ce4a01 100755
--- a/react-ui/vite.config.mjs
+++ b/react-ui/vite.config.mjs
@@ -8,10 +8,11 @@ export default defineConfig({
     },
     // develop server
     server: {
+        host: true,
         port: 3000,
         proxy: {
             '/api': {
-                target: 'http://127.0.0.1:8080',
+                target: 'http://clab-gosdn_csbi_arista_base-gosdn:8080',
                 changeOrigin: true,
                 secure: false,
                 rewrite: (path) => path.replace(/^\/api/, ''),
-- 
GitLab


From 86786eb2b70bb9fa83084eba02a61c6c32c1dbaf Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@@stud.h-da.de>
Date: Tue, 7 Jan 2025 12:45:35 +0100
Subject: [PATCH 16/79] fix ci docker image build path

---
 .gitlab/ci/.build-container-images.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab/ci/.build-container-images.yml b/.gitlab/ci/.build-container-images.yml
index 79e22bc63..7fda52178 100644
--- a/.gitlab/ci/.build-container-images.yml
+++ b/.gitlab/ci/.build-container-images.yml
@@ -78,7 +78,7 @@ build-inventory-manager-image:
 build-react-ui-image:
     script:
         - REACT_UI_IMAGE_NAME="${CI_REGISTRY_IMAGE}/react-ui"
-        - docker buildx build -t "$REACT_UI_IMAGE_NAME:$CI_COMMIT_SHA" -f "${CI_PROJECT_DIR}/react-ui/docker/webserver/Dockerfile" ./react-ui
+        - docker buildx build -t "$REACT_UI_IMAGE_NAME:$CI_COMMIT_SHA" -f "${CI_PROJECT_DIR}/react-ui/docker/webserver/Dockerfile" .
         - docker push "$REACT_UI_IMAGE_NAME:$CI_COMMIT_SHA"
         - docker tag "$REACT_UI_IMAGE_NAME:$CI_COMMIT_SHA" "$REACT_UI_IMAGE_NAME:$CI_COMMIT_REF_SLUG"
         - docker push "$REACT_UI_IMAGE_NAME:$CI_COMMIT_REF_SLUG"
-- 
GitLab


From dc4cdcdaaa87bcae0eaca150d7dff9828382ba02 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Wed, 8 Jan 2025 08:07:42 +0000
Subject: [PATCH 17/79] [renovate] Update module
 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go to
 v1.36.2-20241127180247-a33202765966.1

See merge request danet/gosdn!1146

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 4 ++--
 go.sum | 4 ++++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/go.mod b/go.mod
index 6e4cf99a4..1946630f6 100644
--- a/go.mod
+++ b/go.mod
@@ -25,7 +25,7 @@ require (
 	go.mongodb.org/mongo-driver v1.17.1
 	golang.org/x/sync v0.10.0
 	google.golang.org/grpc v1.69.2
-	google.golang.org/protobuf v1.36.1
+	google.golang.org/protobuf v1.36.2
 	gopkg.in/yaml.v3 v3.0.1
 )
 
@@ -86,7 +86,7 @@ require (
 )
 
 require (
-	buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.1-20241127180247-a33202765966.1
+	buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.2-20241127180247-a33202765966.1
 	github.com/bufbuild/protovalidate-go v0.7.3
 	github.com/hashicorp/go-multierror v1.1.1
 	github.com/hashicorp/go-plugin v1.4.10
diff --git a/go.sum b/go.sum
index e7d3f5158..fe429b64a 100644
--- a/go.sum
+++ b/go.sum
@@ -18,6 +18,8 @@ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-2024112718024
 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20241127180247-a33202765966.1/go.mod h1:mnHCFccv4HwuIAOHNGdiIc5ZYbBCvbTWZcodLN5wITI=
 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.1-20241127180247-a33202765966.1 h1:v223wh/bhlSHSc0tU9PXRWXHhkw3UWMtth7TmYGfHAQ=
 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.1-20241127180247-a33202765966.1/go.mod h1:/zlFuuECgFgewxwW6qQKgvMJ07YZkWlVkcSxEhJprJw=
+buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.2-20241127180247-a33202765966.1 h1:BICM6du/XzvEgeorNo4xgohK3nMTmEPViGyd5t7xVqk=
+buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.2-20241127180247-a33202765966.1/go.mod h1:JnMVLi3qrNYPODVpEKG7UjHLl/d2zR221e66YCSmP2Q=
 cel.dev/expr v0.18.0 h1:CJ6drgk+Hf96lkLikr4rFf19WrU0BOWEihyZnI2TAzo=
 cel.dev/expr v0.18.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
@@ -657,6 +659,8 @@ google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8i
 google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
 google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+google.golang.org/protobuf v1.36.2 h1:R8FeyR1/eLmkutZOM5CWghmo5itiG9z0ktFlTVLuTmU=
+google.golang.org/protobuf v1.36.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
-- 
GitLab


From 6df3abc19a0357cff45fbe3e3e169ee7c4c5b34f Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@@stud.h-da.de>
Date: Wed, 8 Jan 2025 10:32:16 +0100
Subject: [PATCH 18/79] (ui): add dev env script

---
 react-ui/package.json   |  3 ++-
 react-ui/scripts/dev.sh | 11 +++++++++++
 2 files changed, 13 insertions(+), 1 deletion(-)
 create mode 100755 react-ui/scripts/dev.sh

diff --git a/react-ui/package.json b/react-ui/package.json
index 709c5bfcb..4c9271009 100755
--- a/react-ui/package.json
+++ b/react-ui/package.json
@@ -37,7 +37,8 @@
         "build::api": "npx @rtk-query/codegen-openapi ./scripts/openapi-config.json",
         "build": "yarn build::api && yarn build::frontend",
         "lint": "eslint src",
-        "lint::fix": "eslint src --fix"
+        "lint::fix": "eslint src --fix",
+        "dev": "./scripts/dev.sh"
     },
     "eslintConfig": {
         "extends": [
diff --git a/react-ui/scripts/dev.sh b/react-ui/scripts/dev.sh
new file mode 100755
index 000000000..3a2d20885
--- /dev/null
+++ b/react-ui/scripts/dev.sh
@@ -0,0 +1,11 @@
+#!/usr/bin/env sh
+
+docker run \
+    -it \
+    --rm \
+    -v $(pwd):/app \
+    -w /app \
+    -p 127.0.0.1:3000:3000 \
+    --network gosdn-csbi-arista-base-net \
+    node:20-alpine3.20 \
+    npx vite
-- 
GitLab


From f9d974909efc8465433ff37bc7a4cd361a4f711c Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@@stud.h-da.de>
Date: Wed, 8 Jan 2025 11:29:44 +0100
Subject: [PATCH 19/79] wip before changing unsubscribe to category param

---
 .../src/components/devices/api/pnd.fetch.ts   | 14 +++++++
 .../devices/reducer/device.reducer.ts         | 38 +++++++----------
 react-ui/src/index.tsx                        |  1 +
 react-ui/src/shared/api/user.fetch.ts         | 25 +++++++++++
 react-ui/src/shared/helper/debug.ts           |  5 +++
 .../protected.layout/protected.layout.tsx     |  4 +-
 .../src/shared/reducer/routine.reducer.ts     | 42 ++++++++++++++-----
 react-ui/src/shared/reducer/user.reducer.ts   | 30 ++-----------
 react-ui/src/shared/utils/routine.manager.ts  |  2 +-
 9 files changed, 96 insertions(+), 65 deletions(-)
 create mode 100644 react-ui/src/components/devices/api/pnd.fetch.ts
 create mode 100644 react-ui/src/shared/api/user.fetch.ts
 create mode 100644 react-ui/src/shared/helper/debug.ts

diff --git a/react-ui/src/components/devices/api/pnd.fetch.ts b/react-ui/src/components/devices/api/pnd.fetch.ts
new file mode 100644
index 000000000..6e677ab8d
--- /dev/null
+++ b/react-ui/src/components/devices/api/pnd.fetch.ts
@@ -0,0 +1,14 @@
+import { PndServiceGetPndListApiArg, api } from "@api/api"
+import { createAsyncThunk } from "@reduxjs/toolkit"
+import { setPnds } from "../reducer/device.reducer"
+
+export const fetchPnds = createAsyncThunk('device/fetchPnds', (_, thunkApi) => {
+    const payload: PndServiceGetPndListApiArg = {
+        timestamp: new Date().getTime().toString(),
+    }
+
+    const subscription = thunkApi.dispatch(api.endpoints.pndServiceGetPndList.initiate(payload))
+    subscription.unwrap().then((response) => {
+        thunkApi.dispatch(setPnds(response.pnd))
+    })
+})
\ No newline at end of file
diff --git a/react-ui/src/components/devices/reducer/device.reducer.ts b/react-ui/src/components/devices/reducer/device.reducer.ts
index 8e4454bd2..f574509be 100755
--- a/react-ui/src/components/devices/reducer/device.reducer.ts
+++ b/react-ui/src/components/devices/reducer/device.reducer.ts
@@ -1,12 +1,10 @@
 import {
-    api,
     NetworkelementFlattenedManagedNetworkElement,
     NetworkelementManagedNetworkElement,
-    PndPrincipalNetworkDomain,
-    PndServiceGetPndListApiArg,
+    PndPrincipalNetworkDomain
 } from '@api/api'
 import { DeviceViewTabValues } from '@component/devices/view/device.view.tabs'
-import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit'
+import { createSlice, PayloadAction } from '@reduxjs/toolkit'
 import { RootState } from 'src/stores'
 import '../routines/index'
 import { startListening } from '/src/stores/middleware/listener.middleware'
@@ -40,11 +38,11 @@ const deviceSlice = createSlice({
     name: 'device',
     initialState,
     reducers: {
-        setDevices: (state, action: PayloadAction<Device[]>) => {
-            state.devices = action.payload
+        setDevices: (state, action: PayloadAction<Device[] | undefined>) => {
+            state.devices = action.payload || []
         },
-        setPnds: (state, action: PayloadAction<PndPrincipalNetworkDomain[]>) => {
-            state.pnds = action.payload
+        setPnds: (state, action: PayloadAction<PndPrincipalNetworkDomain[] | undefined>) => {
+            state.pnds = action.payload || []
         },
         setActiveTab: (state, action: PayloadAction<DeviceViewTabValues>) => {
             state.activeTab = action.payload
@@ -77,31 +75,23 @@ const deviceSlice = createSlice({
     },
 })
 
-export const { setDevices, setActiveTab, setSelectedDevice, setSelectedMne, setSelectedJson } =
+export const { setDevices, setActiveTab, setSelectedDevice, setSelectedMne, setSelectedJson, setPnds } =
     deviceSlice.actions
-const { setPnds } = deviceSlice.actions
 
 export default deviceSlice.reducer
 export const deviceReducerPath = deviceSlice.reducerPath
 
-export const fetchPnds = createAsyncThunk('device/fetchPnds', (_, thunkApi) => {
-    const payload: PndServiceGetPndListApiArg = {
-        timestamp: new Date().getTime().toString(),
-    }
-
-    const subscription = thunkApi.dispatch(api.endpoints.pndServiceGetPndList.initiate(payload))
-    subscription.unwrap().then((response) => {
-        thunkApi.dispatch(setPnds(response.pnd))
-    })
-})
-
 // add default selected device if no selected device is set
 startListening({
     predicate: (action) => setDevices.match(action),
     effect: async (action, listenerApi) => {
-        const { device } = listenerApi.getOriginalState() as RootState
-        if (!device.selectedDevice && !!action.payload[0]) {
-            listenerApi.dispatch(setSelectedDevice(action.payload[0]))
+        const { device: state } = listenerApi.getOriginalState() as RootState
+        if (state.selectedDevice) {
+            return
         }
+
+        // if there are no devices available do set null
+        const newDevices = action.payload?.[0] || null
+        listenerApi.dispatch(setSelectedDevice(newDevices))
     },
 })
diff --git a/react-ui/src/index.tsx b/react-ui/src/index.tsx
index 8383248ce..3697efd07 100755
--- a/react-ui/src/index.tsx
+++ b/react-ui/src/index.tsx
@@ -16,6 +16,7 @@ import { router } from './routes'
 import './shared/icons/icons'
 import { persistor, store } from './stores'
 
+window.env = window.location.hostname === 'localhost' ? 'development' : 'production';
 
 ReactDOM.createRoot(document.getElementById("root")).render(
     <React.StrictMode>
diff --git a/react-ui/src/shared/api/user.fetch.ts b/react-ui/src/shared/api/user.fetch.ts
new file mode 100644
index 000000000..1b6dd344e
--- /dev/null
+++ b/react-ui/src/shared/api/user.fetch.ts
@@ -0,0 +1,25 @@
+import { createAsyncThunk } from "@reduxjs/toolkit"
+import { setUser } from "@shared/reducer/user.reducer"
+import { RootState } from "src/stores"
+import { api, UserServiceGetUsersApiArg } from "./api"
+
+export const fetchUser = createAsyncThunk('user/fetchUser', (_, thunkAPI) => {
+    const payload: UserServiceGetUsersApiArg = {}
+
+    thunkAPI.dispatch(api.endpoints.userServiceGetUsers.initiate(payload)).then((response) => {
+        if (response.error || !response.data?.user?.length) {
+            // TODO proper error handling
+            throw new Error('Fetching the pnd list after successful login failed')
+        }
+
+        const { user } = thunkAPI.getState() as RootState
+        const matchedUser = response.data.user.find((_user) => _user.name === user.username)
+
+        if (!matchedUser) {
+            // TODO proper error handling
+            throw new Error('No user found with the provided username')
+        }
+
+        thunkAPI.dispatch(setUser(matchedUser))
+    })
+})
diff --git a/react-ui/src/shared/helper/debug.ts b/react-ui/src/shared/helper/debug.ts
new file mode 100644
index 000000000..6628989b8
--- /dev/null
+++ b/react-ui/src/shared/helper/debug.ts
@@ -0,0 +1,5 @@
+export const debugMessage = (message: string) => {
+    if (window?.env === 'development') {
+        console.warn("Debug: \n" + message)
+    }
+}
\ No newline at end of file
diff --git a/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx b/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx
index c7e13c6fe..17b6209a5 100755
--- a/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx
+++ b/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx
@@ -1,12 +1,12 @@
+import { fetchUser } from '@api/user.fetch';
 import logo from '@assets/logo.svg';
-import { fetchPnds } from '@component/devices/reducer/device.reducer';
+import { fetchPnds } from '@component/devices/api/pnd.fetch';
 import { faCircleUser, faRightFromBracket } from "@fortawesome/free-solid-svg-icons";
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { useAppDispatch, useAppSelector } from '@hooks';
 import { useAuth } from "@provider/auth.provider";
 import { MenuProvider } from '@provider/menu/menu.provider';
 import { DEVICE_URL, LOGIN_URL } from '@routes';
-import { fetchUser } from '@shared/reducer/user.reducer';
 import React, { useEffect } from "react";
 import { Dropdown } from "react-bootstrap";
 import { useTranslation } from "react-i18next";
diff --git a/react-ui/src/shared/reducer/routine.reducer.ts b/react-ui/src/shared/reducer/routine.reducer.ts
index a52ee84d3..fc5a4b35b 100755
--- a/react-ui/src/shared/reducer/routine.reducer.ts
+++ b/react-ui/src/shared/reducer/routine.reducer.ts
@@ -1,33 +1,43 @@
+import { debugMessage } from '@helper/debug'
 import { PayloadAction, createSlice } from '@reduxjs/toolkit'
 import { RoutineManager } from '@utils/routine.manager'
 import { RootState } from '../../stores'
 import { startListening } from '../../stores/middleware/listener.middleware'
 import { setToken } from './user.reducer'
 
+// ---------------- thunk types ---------------- 
+
 interface ThunkEntityDTO {
     thunk: any
     payload: Object
 
     /**
-     * Only one subscription per category is allowed. New subscription will unsubscribe and overwrite the old one
+     * Only one subscription per category is allowed.
+     * New subscription will unsubscribe and overwrite the old one
      */
     category: CATEGORIES
 }
 
-interface ThunkEntity extends ThunkEntityDTO {
+/**
+ *  This Wrapper holds the actual thunk information 
+ *  as well as additional information 
+ */
+interface ThunkWrapper extends ThunkEntityDTO {
     id?: number
     locked: boolean
 }
 
-export interface ReducerState {
-    thunks: { [key in keyof typeof CATEGORIES]: ThunkEntity | null }
-}
-
 export enum CATEGORIES {
     TABLE,
     TAB,
 }
 
+// ---------------- reducer types ---------------- 
+
+export interface ReducerState {
+    thunks: { [key in keyof typeof CATEGORIES]: ThunkWrapper | null }
+}
+
 const initialState: ReducerState = {
     thunks: {
         TABLE: null,
@@ -40,7 +50,11 @@ const RoutineSlice = createSlice({
     initialState,
     reducers: {
         addRoutine: (state: any, { payload }: PayloadAction<ThunkEntityDTO>) => {
-            const newThunk: ThunkEntity = { ...payload, locked: true }
+            if (state.thunks[CATEGORIES[payload.category]]?.locked) {
+
+            }
+
+            const newThunk: ThunkWrapper = { ...payload, locked: true }
             state.thunks[CATEGORIES[payload.category]] = newThunk
         },
 
@@ -48,8 +62,8 @@ const RoutineSlice = createSlice({
             const thunk = state.thunks[CATEGORIES[payload.category] as any]
 
             if (!thunk) {
-                // TODO
-                throw new Error('Thunk not found')
+                debugMessage("Desired thunk of category " + payload.category + " is not available")
+                return
             }
 
             state.thunks[CATEGORIES[payload.category] as any] = { ...thunk, id: payload.id, locked: false }
@@ -89,11 +103,17 @@ startListening({
 //     },
 // })
 
-// add new routine
+/**
+ * Add new routine
+ * 
+ * This listener handles the connection between the RoutingManager that 
+ * stores the non persistable thunk object and the peristable thunk information.
+ * The persistable information are stored in this reducer
+ */
 startListening({
     predicate: (action) => addRoutine.match(action),
     effect: async (action, listenerApi) => {
-        const { thunk } = action.payload as ThunkEntity
+        const { thunk } = action.payload as ThunkWrapper
         const subscription = await listenerApi.dispatch(thunk(action.payload.payload))
         const thunkId = await RoutineManager.add(subscription.payload)
         listenerApi.dispatch(
diff --git a/react-ui/src/shared/reducer/user.reducer.ts b/react-ui/src/shared/reducer/user.reducer.ts
index af0f2d171..a0f2d4222 100755
--- a/react-ui/src/shared/reducer/user.reducer.ts
+++ b/react-ui/src/shared/reducer/user.reducer.ts
@@ -1,7 +1,6 @@
-import { api, RbacUser, UserServiceGetUsersApiArg } from '@api/api'
+import { RbacUser } from '@api/api'
 import { setCookieValue } from '@helper/coookie'
-import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit'
-import { RootState } from '..'
+import { createSlice, PayloadAction } from '@reduxjs/toolkit'
 
 export interface UserSliceState {
     // defined by the frontend user input. This value is getting compared with the backend response
@@ -34,27 +33,4 @@ export const { setToken } = userSlice.actions
 export const { setUser } = userSlice.actions
 
 export default userSlice.reducer
-export const userReducerPath = userSlice.reducerPath
-
-export const fetchUser = createAsyncThunk('user/fetchUser', (_, thunkAPI) => {
-    const payload: UserServiceGetUsersApiArg = {}
-
-    thunkAPI.dispatch(api.endpoints.userServiceGetUsers.initiate(payload)).then((response) => {
-        if (response.error || !response.data?.user?.length) {
-            // TODO proper error handling
-            throw new Error('Fetching the pnd list after successful login failed')
-        }
-
-        const { user } = thunkAPI.getState() as RootState
-
-        // TODO ask if this is the correct approach
-        const matchedUser = response.data.user.find((_user) => _user.name === user.username)
-
-        if (!matchedUser) {
-            // TODO proper error handling
-            throw new Error('No user found with the provided username')
-        }
-
-        thunkAPI.dispatch(setUser(matchedUser))
-    })
-})
+export const userReducerPath = userSlice.reducerPath
\ No newline at end of file
diff --git a/react-ui/src/shared/utils/routine.manager.ts b/react-ui/src/shared/utils/routine.manager.ts
index ade079289..2f1a8086a 100755
--- a/react-ui/src/shared/utils/routine.manager.ts
+++ b/react-ui/src/shared/utils/routine.manager.ts
@@ -14,7 +14,7 @@ const initialState = {
 /**
  * Routine manager is a singleton that holds all running routines.
  * The redux store holds any persistable information about the routines.
- * The routines objects itself are stored in the RoutineManager.
+ * The routine objects itself are stored in the RoutineManager.
  */
 export const RoutineManager = (() => {
     const state = initialState
-- 
GitLab


From 4c7056c81a3bb5abdaba075ab85d261dc3560579 Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@@stud.h-da.de>
Date: Wed, 8 Jan 2025 12:55:13 +0100
Subject: [PATCH 20/79] (ui): change routine identification to category

---
 .../src/components/devices/api/pnd.fetch.ts   |  1 +
 .../devices/reducer/device.reducer.ts         | 34 +++++----
 .../devices/routines/device.routine.ts        |  7 +-
 .../devices/routines/mne.routine.ts           | 32 ++++++--
 .../devices/view/device.view.table.tsx        |  2 +-
 .../devices/view/device.view.tabs.tsx         |  2 +-
 .../view_model/device.tabs.viewmodel.ts       |  2 +-
 .../src/components/login/view/login.view.tsx  |  2 +-
 .../json_viewer/view/json_viewer.view.tsx     |  2 +-
 react-ui/src/shared/helper/debug.ts           |  8 +-
 .../src/shared/provider/auth.provider.tsx     |  2 +-
 .../shared/provider/menu/menu.provider.tsx    |  2 +-
 .../src/shared/provider/utils.provider.tsx    |  2 +-
 .../src/shared/reducer/routine.reducer.ts     | 75 ++++--------------
 react-ui/src/shared/types/category.type.ts    | 17 +++++
 .../interfaces.type.ts}                       |  0
 react-ui/src/shared/types/thunk.type.ts       | 12 +++
 react-ui/src/shared/utils/routine.manager.ts  | 76 ++++++++++---------
 18 files changed, 151 insertions(+), 127 deletions(-)
 create mode 100644 react-ui/src/shared/types/category.type.ts
 rename react-ui/src/shared/{helper/interfaces.ts => types/interfaces.type.ts} (100%)
 create mode 100644 react-ui/src/shared/types/thunk.type.ts

diff --git a/react-ui/src/components/devices/api/pnd.fetch.ts b/react-ui/src/components/devices/api/pnd.fetch.ts
index 6e677ab8d..fd49de636 100644
--- a/react-ui/src/components/devices/api/pnd.fetch.ts
+++ b/react-ui/src/components/devices/api/pnd.fetch.ts
@@ -2,6 +2,7 @@ import { PndServiceGetPndListApiArg, api } from "@api/api"
 import { createAsyncThunk } from "@reduxjs/toolkit"
 import { setPnds } from "../reducer/device.reducer"
 
+// TODO rethink this. This should be in the shared part bc its getting invoked in the procteded layout
 export const fetchPnds = createAsyncThunk('device/fetchPnds', (_, thunkApi) => {
     const payload: PndServiceGetPndListApiArg = {
         timestamp: new Date().getTime().toString(),
diff --git a/react-ui/src/components/devices/reducer/device.reducer.ts b/react-ui/src/components/devices/reducer/device.reducer.ts
index f574509be..9d91700c4 100755
--- a/react-ui/src/components/devices/reducer/device.reducer.ts
+++ b/react-ui/src/components/devices/reducer/device.reducer.ts
@@ -11,27 +11,25 @@ import { startListening } from '/src/stores/middleware/listener.middleware'
 
 export type Device = NetworkelementFlattenedManagedNetworkElement
 
-interface SelectedDeviceInterface {
+interface SelectedObject {
     device: Device
     mne: NetworkelementManagedNetworkElement | null
     json: JSON | null
 }
 
-type SelectedDeviceType = SelectedDeviceInterface | null
-
 export interface DeviceSliceState {
     devices: Device[]
     pnds: PndPrincipalNetworkDomain[]
 
     activeTab: DeviceViewTabValues
-    selectedDevice: SelectedDeviceType
+    selected: SelectedObject | null
 }
 
 const initialState: DeviceSliceState = {
     devices: [],
     pnds: [],
     activeTab: DeviceViewTabValues.METADATA,
-    selectedDevice: null,
+    selected: null,
 }
 
 const deviceSlice = createSlice({
@@ -48,29 +46,33 @@ const deviceSlice = createSlice({
             state.activeTab = action.payload
         },
         setSelectedDevice: (state, action: PayloadAction<Device | null>) => {
-            let selectedDevice: SelectedDeviceType = null
+            let selectedObject = null;
             if (action.payload) {
-                selectedDevice = { device: action.payload, mne: null, json: null }
+                selectedObject = { device: action.payload, mne: null, json: null }
             }
 
-            state.selectedDevice = selectedDevice
+            state.selected = selectedObject
         },
         setSelectedMne: (state, action: PayloadAction<NetworkelementManagedNetworkElement>) => {
-            if (!state.selectedDevice) {
-                throw new Error('Selected Device is null where it shouldn´t be null')
+            if (!state.selected) {
+                throw new Error('Can not find corresponding device')
+            }
+
+            // safety check to prevent possible race conditions
+            if (state.selected.device.id !== action.payload.id) {
+                // TODO proper error handling by retry fetching the device object
+                throw new Error('Device and mne id does not match')
             }
 
-            state.selectedDevice.mne = action.payload
-            // TODO maybe don´t take the device of "selected device" instead search in the devices array for the proper device
-            // should not make a diffrence due to pointer but dunno
+            state.selected.mne = action.payload
         },
 
         setSelectedJson: (state, action: PayloadAction<JSON>) => {
-            if (!state.selectedDevice) {
+            if (!state.selected) {
                 throw new Error('Selected Device is null where it shouldn´t be null')
             }
 
-            state.selectedDevice.json = action.payload || null
+            state.selected.json = action.payload || null
         },
     },
 })
@@ -86,7 +88,7 @@ startListening({
     predicate: (action) => setDevices.match(action),
     effect: async (action, listenerApi) => {
         const { device: state } = listenerApi.getOriginalState() as RootState
-        if (state.selectedDevice) {
+        if (state.selected) {
             return
         }
 
diff --git a/react-ui/src/components/devices/routines/device.routine.ts b/react-ui/src/components/devices/routines/device.routine.ts
index 10caffa2f..f9b3e1ee2 100755
--- a/react-ui/src/components/devices/routines/device.routine.ts
+++ b/react-ui/src/components/devices/routines/device.routine.ts
@@ -19,8 +19,13 @@ startListening({
 export const fetchDevicesThunk = createAsyncThunk(FETCH_DEVICE_ACTION, (_, thunkApi) => {
     const { user } = thunkApi.getState() as RootState
 
+    if (!user.user?.roles) {
+        throw new Error('Background MNE fetching failed! User data is missing. Reload page or logout and login again')
+        // TODO
+    }
+
     const payload: NetworkElementServiceGetAllFlattenedApiArg = {
-        pid: Object.keys(user?.user.roles)[0],
+        pid: Object.keys(user.user.roles)[0],
         timestamp: new Date().getTime().toString(),
     }
 
diff --git a/react-ui/src/components/devices/routines/mne.routine.ts b/react-ui/src/components/devices/routines/mne.routine.ts
index 7de1d1814..a3ea43d2f 100755
--- a/react-ui/src/components/devices/routines/mne.routine.ts
+++ b/react-ui/src/components/devices/routines/mne.routine.ts
@@ -6,26 +6,38 @@ import {
     setSelectedMne,
 } from '@component/devices/reducer/device.reducer'
 import { createAsyncThunk } from '@reduxjs/toolkit'
-import { addRoutine, CATEGORIES } from '@shared/reducer/routine.reducer'
+import { addRoutine } from '@shared/reducer/routine.reducer'
+import { Category } from '@shared/types/category.type'
 import { RootState } from 'src/stores'
 import { startListening } from '../../../stores/middleware/listener.middleware'
 
 export const FETCH_MNE_ACTION = 'subscription/device/fetchSelectedMNE'
 
-// fetch mne if selected device is set
+/**
+ * #0
+ * Trigger fetch MNE (#1)
+ * 
+ * Triggered by a selectedDevice
+ */
 startListening({
     predicate: (action) => setSelectedDevice.match(action) && !!action.payload,
     effect: async (action, listenerApi) => {
         listenerApi.dispatch(
             addRoutine({
                 thunk: fetchSelectedMneThunk,
-                category: CATEGORIES.TAB,
+                category: Category.TAB,
                 payload: action.payload,
             })
         )
     },
 })
 
+/**
+ * #1
+ * Fetch MNE
+ * 
+ * Triggered by #0
+ */
 const FETCH_MNE_INTERVAL = 5000 // in ms
 export const fetchSelectedMneThunk = createAsyncThunk(
     FETCH_MNE_ACTION,
@@ -56,7 +68,12 @@ export const fetchSelectedMneThunk = createAsyncThunk(
     }
 )
 
-// save fetched mne
+/**
+ * #2
+ * Received MNE
+ * 
+ * Triggered by #1
+ */
 startListening({
     predicate: (action) => api.endpoints.networkElementServiceGet.matchFulfilled(action),
     effect: async (action, listenerApi) => {
@@ -64,7 +81,12 @@ startListening({
     },
 })
 
-// save fetched mne
+/**
+ * #3
+ * Fetch & receive json
+ * 
+ * Triggered by #2
+ */
 startListening({
     predicate: (action) => setSelectedMne.match(action),
     effect: async (action, listenerApi) => {
diff --git a/react-ui/src/components/devices/view/device.view.table.tsx b/react-ui/src/components/devices/view/device.view.table.tsx
index 312caab60..9b731fef5 100755
--- a/react-ui/src/components/devices/view/device.view.table.tsx
+++ b/react-ui/src/components/devices/view/device.view.table.tsx
@@ -5,7 +5,7 @@ import { useTranslation } from "react-i18next";
 import { useDeviceTableViewModel } from "../view_model/device.table.viewmodel";
 
 export const DeviceViewTable = (searchRef: MutableRefObject<HTMLInputElement>) => {
-    const { devices, pnds, selectedDevice } = useAppSelector(state => state.device);
+    const { devices, pnds, selected: selectedDevice } = useAppSelector(state => state.device);
     const { t } = useTranslation('common');
     const { trClickHandler } = useDeviceTableViewModel(searchRef);
 
diff --git a/react-ui/src/components/devices/view/device.view.tabs.tsx b/react-ui/src/components/devices/view/device.view.tabs.tsx
index 2929f9b64..a2768a0ea 100755
--- a/react-ui/src/components/devices/view/device.view.tabs.tsx
+++ b/react-ui/src/components/devices/view/device.view.tabs.tsx
@@ -8,7 +8,7 @@ export enum DeviceViewTabValues {
 }
 
 export const DeviceViewTabs = (activeTab: DeviceViewTabValues) => {
-    const { selectedDevice } = useAppSelector(state => state.device);
+    const { selected: selectedDevice } = useAppSelector(state => state.device);
     const { jsonYang } = useDeviceTabsViewModel();
 
     const metadataTab = () => {
diff --git a/react-ui/src/components/devices/view_model/device.tabs.viewmodel.ts b/react-ui/src/components/devices/view_model/device.tabs.viewmodel.ts
index 4a60567b6..af4cc3abb 100755
--- a/react-ui/src/components/devices/view_model/device.tabs.viewmodel.ts
+++ b/react-ui/src/components/devices/view_model/device.tabs.viewmodel.ts
@@ -7,7 +7,7 @@ export enum DeviceViewTabValues {
 }
 
 export const useDeviceTabsViewModel = () => {
-    const { selectedDevice } = useAppSelector((state) => state.device)
+    const { selected: selectedDevice } = useAppSelector((state) => state.device)
 
     const getYangModelJSON = (): JSON | null => {
         if (!selectedDevice?.json) {
diff --git a/react-ui/src/components/login/view/login.view.tsx b/react-ui/src/components/login/view/login.view.tsx
index 03d7406f4..38afc83a1 100755
--- a/react-ui/src/components/login/view/login.view.tsx
+++ b/react-ui/src/components/login/view/login.view.tsx
@@ -1,5 +1,5 @@
 import logo from '@assets/logo.svg'
-import { BasicProp } from '@helper/interfaces'
+import { BasicProp } from '@shared/types/interfaces.type'
 import React, { useRef } from 'react'
 import { Alert, Button, Col, Container, Form, Image, Row, Spinner } from 'react-bootstrap'
 import { useTranslation } from 'react-i18next'
diff --git a/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx b/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx
index 720f75c7d..b8358c686 100755
--- a/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx
+++ b/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx
@@ -130,7 +130,7 @@ export const JsonViewer = ({ json }: JsonViewerProbs) => {
     const searchHTML = () => {
         return (
             <>
-                <Form.Group controlId='device.search' className='p-0 mx-1 pt-2'>
+                <Form.Group controlId='json_viewer.search' className='p-0 mx-1 pt-2'>
                     <Form.Control type="text" placeholder={t('device.search.placeholder')} ref={search} />
                 </Form.Group>
             </>
diff --git a/react-ui/src/shared/helper/debug.ts b/react-ui/src/shared/helper/debug.ts
index 6628989b8..db10a0979 100644
--- a/react-ui/src/shared/helper/debug.ts
+++ b/react-ui/src/shared/helper/debug.ts
@@ -1,5 +1,11 @@
-export const debugMessage = (message: string) => {
+export const warnMessage = (message: string) => {
     if (window?.env === 'development') {
         console.warn("Debug: \n" + message)
     }
+}
+
+export const infoMessage = (message: string) => {
+    if (window?.env === 'development') {
+        console.info("Info: \n" + message)
+    }
 }
\ No newline at end of file
diff --git a/react-ui/src/shared/provider/auth.provider.tsx b/react-ui/src/shared/provider/auth.provider.tsx
index 69bdccbdf..77219bdce 100755
--- a/react-ui/src/shared/provider/auth.provider.tsx
+++ b/react-ui/src/shared/provider/auth.provider.tsx
@@ -1,8 +1,8 @@
 import { AuthServiceLoginApiArg, AuthServiceLoginApiResponse, useAuthServiceLoginMutation } from "@api/api";
 import { getCookieValue } from "@helper/coookie";
-import { BasicProp } from "@helper/interfaces";
 import { useAppDispatch, useAppSelector } from "@hooks";
 import { DEVICE_URL, LOGIN_URL } from "@routes";
+import { BasicProp } from "@shared/types/interfaces.type";
 import { jwtDecode } from "jwt-decode";
 import { createContext, useContext, useEffect, useMemo } from "react";
 import { useNavigate } from "react-router-dom";
diff --git a/react-ui/src/shared/provider/menu/menu.provider.tsx b/react-ui/src/shared/provider/menu/menu.provider.tsx
index a91f46639..b2525692b 100644
--- a/react-ui/src/shared/provider/menu/menu.provider.tsx
+++ b/react-ui/src/shared/provider/menu/menu.provider.tsx
@@ -1,7 +1,7 @@
 import { faRightFromBracket, IconDefinition } from "@fortawesome/free-solid-svg-icons";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { BasicProp } from "@helper/interfaces";
 import { useAuth } from "@provider/auth.provider";
+import { BasicProp } from "@shared/types/interfaces.type";
 import React, { createContext, useContext, useEffect, useMemo, useState } from "react";
 import { useTranslation } from "react-i18next";
 import './menu.provider.scss';
diff --git a/react-ui/src/shared/provider/utils.provider.tsx b/react-ui/src/shared/provider/utils.provider.tsx
index ca6aa1d32..3a76bbe69 100644
--- a/react-ui/src/shared/provider/utils.provider.tsx
+++ b/react-ui/src/shared/provider/utils.provider.tsx
@@ -1,4 +1,4 @@
-import { BasicProp } from "@helper/interfaces";
+import { BasicProp } from "@shared/types/interfaces.type";
 import React, { createContext, useContext, useMemo } from "react";
 import { useTranslation } from "react-i18next";
 import { toast } from "react-toastify";
diff --git a/react-ui/src/shared/reducer/routine.reducer.ts b/react-ui/src/shared/reducer/routine.reducer.ts
index fc5a4b35b..873d7d6a2 100755
--- a/react-ui/src/shared/reducer/routine.reducer.ts
+++ b/react-ui/src/shared/reducer/routine.reducer.ts
@@ -1,72 +1,31 @@
-import { debugMessage } from '@helper/debug'
 import { PayloadAction, createSlice } from '@reduxjs/toolkit'
+import { CategoryType } from '@shared/types/category.type'
+import { ThunkEntityDTO } from '@shared/types/thunk.type'
 import { RoutineManager } from '@utils/routine.manager'
 import { RootState } from '../../stores'
 import { startListening } from '../../stores/middleware/listener.middleware'
 import { setToken } from './user.reducer'
 
-// ---------------- thunk types ---------------- 
-
-interface ThunkEntityDTO {
-    thunk: any
-    payload: Object
-
-    /**
-     * Only one subscription per category is allowed.
-     * New subscription will unsubscribe and overwrite the old one
-     */
-    category: CATEGORIES
-}
-
-/**
- *  This Wrapper holds the actual thunk information 
- *  as well as additional information 
- */
-interface ThunkWrapper extends ThunkEntityDTO {
-    id?: number
-    locked: boolean
-}
-
-export enum CATEGORIES {
-    TABLE,
-    TAB,
-}
-
-// ---------------- reducer types ---------------- 
-
 export interface ReducerState {
-    thunks: { [key in keyof typeof CATEGORIES]: ThunkWrapper | null }
+    thunks: Record<CategoryType, ThunkEntityDTO | null>
 }
 
 const initialState: ReducerState = {
     thunks: {
+        DEVICE: null,
         TABLE: null,
-        TAB: null,
+        TAB: null
     },
 }
 
+
 const RoutineSlice = createSlice({
     name: 'routine',
     initialState,
     reducers: {
         addRoutine: (state: any, { payload }: PayloadAction<ThunkEntityDTO>) => {
-            if (state.thunks[CATEGORIES[payload.category]]?.locked) {
-
-            }
-
-            const newThunk: ThunkWrapper = { ...payload, locked: true }
-            state.thunks[CATEGORIES[payload.category]] = newThunk
-        },
-
-        setThunkId: (state, { payload }: PayloadAction<{ id: number; category: CATEGORIES }>) => {
-            const thunk = state.thunks[CATEGORIES[payload.category] as any]
-
-            if (!thunk) {
-                debugMessage("Desired thunk of category " + payload.category + " is not available")
-                return
-            }
-
-            state.thunks[CATEGORIES[payload.category] as any] = { ...thunk, id: payload.id, locked: false }
+            const newThunk: ThunkEntityDTO = payload
+            state.thunks[payload.category] = newThunk
         },
 
         removeAll: (state) => {
@@ -113,12 +72,9 @@ startListening({
 startListening({
     predicate: (action) => addRoutine.match(action),
     effect: async (action, listenerApi) => {
-        const { thunk } = action.payload as ThunkWrapper
+        const { thunk } = action.payload as ThunkEntityDTO
         const subscription = await listenerApi.dispatch(thunk(action.payload.payload))
-        const thunkId = await RoutineManager.add(subscription.payload)
-        listenerApi.dispatch(
-            RoutineSlice.actions.setThunkId({ id: thunkId, category: action.payload.category })
-        )
+        RoutineManager.add(subscription.payload, action.payload.category)
     },
 })
 
@@ -127,14 +83,11 @@ startListening({
     predicate: (action) => addRoutine.match(action),
     effect: async (action, listenerApi) => {
         const { routine } = listenerApi.getOriginalState() as RootState
-        const lastThunk = routine.thunks[CATEGORIES[action.payload.category] as any]
-        if (lastThunk) {
-            if (!lastThunk.id) {
-                throw new Error()
-                // TODO
-            }
+        const category = action.payload.category;
 
-            RoutineManager.unsubscribe(lastThunk.id)
+        const lastThunk = routine.thunks[category as CategoryType]
+        if (lastThunk) {
+            RoutineManager.unsubscribe(category)
         }
     },
 })
diff --git a/react-ui/src/shared/types/category.type.ts b/react-ui/src/shared/types/category.type.ts
new file mode 100644
index 000000000..e08282341
--- /dev/null
+++ b/react-ui/src/shared/types/category.type.ts
@@ -0,0 +1,17 @@
+
+const DeviceListView = {
+    TABLE: "device_list/table",
+    TAB: "device_list/tab",
+}
+
+const Shared = {
+    DEVICE: 'objects/device'
+}
+
+
+export const Category = {
+    ...DeviceListView,
+    ...Shared
+}
+
+export type CategoryType = keyof typeof Category
\ No newline at end of file
diff --git a/react-ui/src/shared/helper/interfaces.ts b/react-ui/src/shared/types/interfaces.type.ts
similarity index 100%
rename from react-ui/src/shared/helper/interfaces.ts
rename to react-ui/src/shared/types/interfaces.type.ts
diff --git a/react-ui/src/shared/types/thunk.type.ts b/react-ui/src/shared/types/thunk.type.ts
new file mode 100644
index 000000000..ef0a92b87
--- /dev/null
+++ b/react-ui/src/shared/types/thunk.type.ts
@@ -0,0 +1,12 @@
+import { CategoryType } from "./category.type"
+
+export interface ThunkEntityDTO {
+    thunk: any
+    payload: Object
+
+    /**
+     * Only one subscription per category is allowed.
+     * New subscription will unsubscribe and overwrite the old one
+     */
+    category: CategoryType
+}
\ No newline at end of file
diff --git a/react-ui/src/shared/utils/routine.manager.ts b/react-ui/src/shared/utils/routine.manager.ts
index 2f1a8086a..427043e24 100755
--- a/react-ui/src/shared/utils/routine.manager.ts
+++ b/react-ui/src/shared/utils/routine.manager.ts
@@ -1,67 +1,73 @@
+import { infoMessage, warnMessage } from '@helper/debug'
 import { QueryActionCreatorResult } from '@reduxjs/toolkit/query'
+import { Category, CategoryType } from '@shared/types/category.type'
 
 type Routine = QueryActionCreatorResult<any>
 
 interface Entity {
     routine: Routine
-    id: number
 }
 
-const initialState = {
-    routines: [] as Entity[],
+
+interface RoutineState {
+    routines: Record<CategoryType, Entity | null>
+}
+
+const initalState: RoutineState = {
+    routines: {
+        DEVICE: null,
+        TABLE: null,
+        TAB: null
+    }
 }
 
 /**
- * Routine manager is a singleton that holds all running routines.
- * The redux store holds any persistable information about the routines.
- * The routine objects itself are stored in the RoutineManager.
- */
+* Routine manager is a singleton that holds all running routines.
+* The redux store holds any persistable information about the routines.
+* The routine objects itself are stored in the RoutineManager.
+*/
 export const RoutineManager = (() => {
-    const state = initialState
-    const add = (routine: Routine): number => {
-        const id = state.routines.length
+    let state = initalState
 
-        const newEntity: Entity = {
+    const add = (routine: Routine, category: CategoryType): boolean => {
+        const entity: Entity = {
             routine: routine,
-            id,
         }
 
-        state.routines = [...state.routines, newEntity]
-
-        return id
+        state.routines = {
+            ...state.routines,
+            [category]: entity
+        }
+        return true
     }
 
     const unsubscribeAll = () => {
-        state.routines.forEach(({ routine: subscription }) => {
-            _unsubscribe(subscription)
-        })
+        Object.keys(state.routines)
+            .forEach((category) => {
+                unsubscribe(category as CategoryType)
+            })
 
-        state.routines = initialState.routines
+        state = initalState
     }
 
     /**
      * @param id
      * @returns returns true if the routine was stopped, false if it was not found
      */
-    const unsubscribe = (id: number): boolean => {
-        const routine = state.routines.find(({ id: routineId }) => routineId === id)
+    const unsubscribe = (category: CategoryType): boolean => {
+        const entity = state.routines[category]
 
-        if (routine) {
-            _unsubscribe(routine.routine)
+        if (entity) {
+            entity.routine.unsubscribe()
+            state.routines[category] = null
+            infoMessage("Routine unsubscribed from category " + category)
         }
 
-        return !!routine
-    }
+        if (!!entity) {
+            warnMessage("Desired routine to unsubscribe does not exist in category " + Category[category])
+        }
 
-    /**
-     * Actual unsubscribe process.
-     * This process is extracted to have a single process of unsubscribing.
-     *
-     * @param subscription
-     */
-    const _unsubscribe = (subscription: Routine) => {
-        subscription.unsubscribe()
-        // TODO remove from state
+        return !!entity
     }
 
     return {
@@ -69,4 +75,4 @@ export const RoutineManager = (() => {
         unsubscribe,
         unsubscribeAll,
     }
-})()
+})()
\ No newline at end of file
-- 
GitLab


From d2720ef07c3fdda3d734f989baf5a9238c628c64 Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@@stud.h-da.de>
Date: Wed, 8 Jan 2025 15:23:36 +0100
Subject: [PATCH 21/79] (ui): refactor rehydration routine subscriptions

---
 .../devices/reducer/device.reducer.ts         | 26 ++++++---
 .../devices/routines/mne.routine.ts           | 12 +++--
 react-ui/src/index.tsx                        |  8 +++
 react-ui/src/shared/api/user.fetch.ts         |  2 +-
 .../src/shared/reducer/routine.reducer.ts     | 54 ++++++++++++-------
 react-ui/src/shared/types/thunk.type.ts       | 26 +++++++--
 .../shared/utils/routine-holder.singleton.ts  | 47 ++++++++++++++++
 react-ui/src/shared/utils/routine.manager.ts  |  2 +
 8 files changed, 142 insertions(+), 35 deletions(-)
 create mode 100644 react-ui/src/shared/utils/routine-holder.singleton.ts

diff --git a/react-ui/src/components/devices/reducer/device.reducer.ts b/react-ui/src/components/devices/reducer/device.reducer.ts
index 9d91700c4..4afcba788 100755
--- a/react-ui/src/components/devices/reducer/device.reducer.ts
+++ b/react-ui/src/components/devices/reducer/device.reducer.ts
@@ -45,13 +45,27 @@ const deviceSlice = createSlice({
         setActiveTab: (state, action: PayloadAction<DeviceViewTabValues>) => {
             state.activeTab = action.payload
         },
-        setSelectedDevice: (state, action: PayloadAction<Device | null>) => {
-            let selectedObject = null;
-            if (action.payload) {
-                selectedObject = { device: action.payload, mne: null, json: null }
-            }
+        setSelectedDevice: {
+            reducer: (state, action: PayloadAction<Device | null, string, { skipListener?: boolean }>) => {
+                // do thing if desired device is already selected
+                if (state.selected?.device.id === action.payload?.id) {
+                    action.meta.skipListener = true
+                    return
+                }
+
+                let selectedObject = null;
+                if (action.payload) {
+                    selectedObject = { device: action.payload, mne: null, json: null }
+                }
 
-            state.selected = selectedObject
+                state.selected = selectedObject
+            },
+            prepare: (device: Device | null) => {
+                return {
+                    payload: device,
+                    meta: { skipListener: false } // set to true when needed
+                }
+            }
         },
         setSelectedMne: (state, action: PayloadAction<NetworkelementManagedNetworkElement>) => {
             if (!state.selected) {
diff --git a/react-ui/src/components/devices/routines/mne.routine.ts b/react-ui/src/components/devices/routines/mne.routine.ts
index a3ea43d2f..876317dd2 100755
--- a/react-ui/src/components/devices/routines/mne.routine.ts
+++ b/react-ui/src/components/devices/routines/mne.routine.ts
@@ -7,7 +7,8 @@ import {
 } from '@component/devices/reducer/device.reducer'
 import { createAsyncThunk } from '@reduxjs/toolkit'
 import { addRoutine } from '@shared/reducer/routine.reducer'
-import { Category } from '@shared/types/category.type'
+import { Category, CategoryType } from '@shared/types/category.type'
+import { RoutineHolderSingleton } from '@utils/routine-holder.singleton'
 import { RootState } from 'src/stores'
 import { startListening } from '../../../stores/middleware/listener.middleware'
 
@@ -20,13 +21,14 @@ export const FETCH_MNE_ACTION = 'subscription/device/fetchSelectedMNE'
  * Triggered by a selectedDevice
  */
 startListening({
-    predicate: (action) => setSelectedDevice.match(action) && !!action.payload,
+    predicate: (action) => setSelectedDevice.match(action) && !!action.payload && !action.meta?.skipListener,
     effect: async (action, listenerApi) => {
+        const factory = RoutineHolderSingleton.getInstance();
         listenerApi.dispatch(
             addRoutine({
-                thunk: fetchSelectedMneThunk,
-                category: Category.TAB,
-                payload: action.payload,
+                thunk: factory.getRoutineByName("fetchSelectedMneThunk"),
+                category: Category.TAB as CategoryType,
+                payload: action.payload as Object,
             })
         )
     },
diff --git a/react-ui/src/index.tsx b/react-ui/src/index.tsx
index 3697efd07..559e1bc54 100755
--- a/react-ui/src/index.tsx
+++ b/react-ui/src/index.tsx
@@ -1,4 +1,6 @@
+import { fetchSelectedMneThunk } from '@component/devices/routines/mne.routine'
 import { UtilsProvider } from '@provider/utils.provider'
+import { RoutineHolderSingleton } from '@utils/routine-holder.singleton'
 import i18next from 'i18next'
 import React from 'react'
 import ReactDOM from 'react-dom/client'
@@ -18,6 +20,12 @@ import { persistor, store } from './stores'
 
 window.env = window.location.hostname === 'localhost' ? 'development' : 'production';
 
+const factory = RoutineHolderSingleton.getInstance();
+factory.registerRoutine("fetchSelectedMneThunk", {
+    func: fetchSelectedMneThunk,
+    id: 0
+});
+
 ReactDOM.createRoot(document.getElementById("root")).render(
     <React.StrictMode>
         <ErrorBoundary fallback={<div>Something went wrong</div>}>
diff --git a/react-ui/src/shared/api/user.fetch.ts b/react-ui/src/shared/api/user.fetch.ts
index 1b6dd344e..08806783b 100644
--- a/react-ui/src/shared/api/user.fetch.ts
+++ b/react-ui/src/shared/api/user.fetch.ts
@@ -16,7 +16,7 @@ export const fetchUser = createAsyncThunk('user/fetchUser', (_, thunkAPI) => {
         const matchedUser = response.data.user.find((_user) => _user.name === user.username)
 
         if (!matchedUser) {
-            // TODO proper error handling
+            // TODO proper error handling => logout
             throw new Error('No user found with the provided username')
         }
 
diff --git a/react-ui/src/shared/reducer/routine.reducer.ts b/react-ui/src/shared/reducer/routine.reducer.ts
index 873d7d6a2..f8c8c31eb 100755
--- a/react-ui/src/shared/reducer/routine.reducer.ts
+++ b/react-ui/src/shared/reducer/routine.reducer.ts
@@ -1,13 +1,15 @@
 import { PayloadAction, createSlice } from '@reduxjs/toolkit'
 import { CategoryType } from '@shared/types/category.type'
-import { ThunkEntityDTO } from '@shared/types/thunk.type'
+import { ThunkDTO, ThunkPersist } from '@shared/types/thunk.type'
+import { RoutineHolderSingleton } from '@utils/routine-holder.singleton'
 import { RoutineManager } from '@utils/routine.manager'
+import { REHYDRATE } from 'redux-persist'
 import { RootState } from '../../stores'
 import { startListening } from '../../stores/middleware/listener.middleware'
 import { setToken } from './user.reducer'
 
 export interface ReducerState {
-    thunks: Record<CategoryType, ThunkEntityDTO | null>
+    thunks: Record<CategoryType, ThunkPersist | null>
 }
 
 const initialState: ReducerState = {
@@ -23,9 +25,14 @@ const RoutineSlice = createSlice({
     name: 'routine',
     initialState,
     reducers: {
-        addRoutine: (state: any, { payload }: PayloadAction<ThunkEntityDTO>) => {
-            const newThunk: ThunkEntityDTO = payload
-            state.thunks[payload.category] = newThunk
+        addRoutine: (state: any, { payload }: PayloadAction<ThunkDTO>) => {
+            const thunk: ThunkPersist = {
+                category: payload.category,
+                payload: payload.payload,
+                thunkId: payload.thunk.id
+            }
+
+            state.thunks[payload.category] = thunk
         },
 
         removeAll: (state) => {
@@ -48,19 +55,26 @@ startListening({
 // on rehydrate add all persistet routines
 // TODO -> thunk does not have the thunk function object due to its coming from the store that ignores the value.
 // at this point we have to figure out how to get the thunk function out of the "string" name
-// startListening({
-//     predicate: ({ type }) => type === REHYDRATE,
-//     effect: async (_, listenerApi) => {
-//         const { routine } = listenerApi.getState() as RootState
-//         for (const [_, thunk] of Object.entries<ThunkEntity>(routine.thunks)) {
-//             if (!thunk) {
-//                 continue
-//             }
-//             const dto: ThunkEntityDTO = thunk
-//             listenerApi.dispatch(addRoutine(dto))
-//         }
-//     },
-// })
+startListening({
+    predicate: ({ type }) => type === REHYDRATE,
+    effect: async (_, listenerApi) => {
+        const { routine } = listenerApi.getState() as RootState
+        const routines = RoutineHolderSingleton.getInstance()
+
+        Object.values(routine.thunks)
+            .filter(thunk => !!thunk)
+            .forEach(thunk => {
+                const container = routines.getRoutineById(thunk.thunkId)
+                const dto: ThunkDTO = {
+                    category: thunk.category,
+                    payload: thunk.payload,
+                    thunk: container
+                }
+
+                listenerApi.dispatch(addRoutine(dto))
+            })
+    },
+})
 
 /**
  * Add new routine
@@ -72,8 +86,8 @@ startListening({
 startListening({
     predicate: (action) => addRoutine.match(action),
     effect: async (action, listenerApi) => {
-        const { thunk } = action.payload as ThunkEntityDTO
-        const subscription = await listenerApi.dispatch(thunk(action.payload.payload))
+        const { thunk } = action.payload as ThunkDTO
+        const subscription = await listenerApi.dispatch(thunk.func(action.payload.payload))
         RoutineManager.add(subscription.payload, action.payload.category)
     },
 })
diff --git a/react-ui/src/shared/types/thunk.type.ts b/react-ui/src/shared/types/thunk.type.ts
index ef0a92b87..90b846039 100644
--- a/react-ui/src/shared/types/thunk.type.ts
+++ b/react-ui/src/shared/types/thunk.type.ts
@@ -1,7 +1,21 @@
 import { CategoryType } from "./category.type"
 
-export interface ThunkEntityDTO {
-    thunk: any
+
+/**
+ * Contains the thunk function combined with a unique id
+ * Giving a explicit id (and not the index of the object)
+ * prevents missmatching the function if a update changes
+ * the RoutineList object length 
+ */
+export interface ThunkContainer {
+    id: number
+    func: any,
+}
+
+
+export interface ThunkDTO {
+    thunk: ThunkContainer
+
     payload: Object
 
     /**
@@ -9,4 +23,10 @@ export interface ThunkEntityDTO {
      * New subscription will unsubscribe and overwrite the old one
      */
     category: CategoryType
-}
\ No newline at end of file
+}
+
+export interface ThunkPersist {
+    thunkId: number,
+    payload: Object
+    category: CategoryType
+}
diff --git a/react-ui/src/shared/utils/routine-holder.singleton.ts b/react-ui/src/shared/utils/routine-holder.singleton.ts
new file mode 100644
index 000000000..47332ab0b
--- /dev/null
+++ b/react-ui/src/shared/utils/routine-holder.singleton.ts
@@ -0,0 +1,47 @@
+import { ThunkContainer } from "@shared/types/thunk.type";
+
+interface LocalThunkContainer {
+    container: ThunkContainer,
+    name: string
+}
+
+export class RoutineHolderSingleton {
+    private static instance: RoutineHolderSingleton;
+    private routineList: Array<LocalThunkContainer> = []
+
+    private constructor() { }
+
+    static getInstance(): RoutineHolderSingleton {
+        if (!RoutineHolderSingleton.instance) {
+            RoutineHolderSingleton.instance = new RoutineHolderSingleton();
+        }
+        return RoutineHolderSingleton.instance;
+    }
+
+    registerRoutine(name: string, thunk: ThunkContainer) {
+        this.routineList = [...this.routineList, { container: thunk, name }];
+    }
+
+    getRoutineById(id: number): ThunkContainer {
+        const routine = this.routineList.find((thunk) => thunk.container.id === id)
+
+        if (!routine) {
+            throw new Error('')
+            // TODO
+        }
+
+        return routine.container;
+    }
+
+
+    getRoutineByName(name: string): ThunkContainer {
+        const routine = this.routineList.find((thunk) => thunk.name === name)
+
+        if (!routine) {
+            throw new Error('')
+            // TODO
+        }
+
+        return routine.container;
+    }
+}
\ No newline at end of file
diff --git a/react-ui/src/shared/utils/routine.manager.ts b/react-ui/src/shared/utils/routine.manager.ts
index 427043e24..1fee6723e 100755
--- a/react-ui/src/shared/utils/routine.manager.ts
+++ b/react-ui/src/shared/utils/routine.manager.ts
@@ -38,6 +38,8 @@ export const RoutineManager = (() => {
             ...state.routines,
             [category]: entity
         }
+        infoMessage("Routine subscribed to category " + category)
+
         return true
     }
 
-- 
GitLab


From 26b786918a85d2a801cd55297980d5d97180679f Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@@stud.h-da.de>
Date: Wed, 8 Jan 2025 16:54:39 +0100
Subject: [PATCH 22/79] (ui): chunked bundles size | improved nginx config |
 further performance improvements

---
 react-ui/docker/webserver/Dockerfile          |   6 +-
 react-ui/docker/webserver/nginx.conf          | 142 +++++++++---------
 react-ui/package.json                         |  64 ++++----
 react-ui/public/fonts/inter-webfont.woff      | Bin 0 -> 26796 bytes
 react-ui/public/fonts/inter-webfont.woff2     | Bin 0 -> 21204 bytes
 .../components/devices/view/device.view.tsx   |   2 +-
 .../components/login/layouts/login.layout.tsx |   4 +-
 react-ui/src/routes.tsx                       |  34 ++++-
 react-ui/src/shared/icons/icons.ts            |   4 +-
 react-ui/src/shared/style/fonts.scss          |   9 +-
 react-ui/vite.config.mjs                      |  28 +++-
 react-ui/yarn.lock                            |  61 ++++++++
 12 files changed, 232 insertions(+), 122 deletions(-)
 create mode 100644 react-ui/public/fonts/inter-webfont.woff
 create mode 100644 react-ui/public/fonts/inter-webfont.woff2

diff --git a/react-ui/docker/webserver/Dockerfile b/react-ui/docker/webserver/Dockerfile
index 71127c09b..9c4f3f676 100644
--- a/react-ui/docker/webserver/Dockerfile
+++ b/react-ui/docker/webserver/Dockerfile
@@ -3,7 +3,11 @@ FROM node:alpine3.20 as builder
 COPY  ./api/openapiv2/gosdn_northbound.swagger.json /app/api/openapiv2/gosdn_northbound.swagger.json
 COPY ./react-ui /app/react-ui
 
-RUN cd /app/react-ui && yarn && yarn build
+RUN cd /app/react-ui && \
+    rm -rf node_modules && \
+    rm yarn.lock && \
+    yarn install --production && \
+    yarn build
 
 
 # webserver
diff --git a/react-ui/docker/webserver/nginx.conf b/react-ui/docker/webserver/nginx.conf
index eb4fc2be9..4ddf7f20d 100644
--- a/react-ui/docker/webserver/nginx.conf
+++ b/react-ui/docker/webserver/nginx.conf
@@ -1,51 +1,82 @@
-
-#user  nobody;
 worker_processes  1;
 
-#error_log  logs/error.log;
-#error_log  logs/error.log  notice;
-#error_log  logs/error.log  info;
-
-#pid        logs/nginx.pid;
-
-
 events {
     worker_connections  1024;
+    multi_accept on;
+    use epoll;
 }
 
 http {
     include       mime.types;
     default_type  application/octet-stream;
 
-    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
-    #                  '$status $body_bytes_sent "$http_referer" '
-    #                  '"$http_user_agent" "$http_x_forwarded_for"';
-
-    #access_log  logs/access.log  main;
-
-    sendfile        on;
-    #tcp_nopush     on;
-
-    #keepalive_timeout  0;
-    keepalive_timeout  65;
+    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
+                    '$status $body_bytes_sent "$http_referer" '
+                    '"$http_user_agent" "$http_x_forwarded_for"';
+
+    access_log /var/log/nginx/access.log main buffer=16k;
+
+    sendfile on;
+    tcp_nopush on;
+    tcp_nodelay on;
+    keepalive_timeout 65;
+    types_hash_max_size 2048;
+    server_tokens off;
+
+    # Buffer size settings
+    client_body_buffer_size 10K;
+    client_header_buffer_size 1k;
+    client_max_body_size 8m;
+    large_client_header_buffers 2 1k;
+
+    # File descriptor cache
+    open_file_cache max=2000 inactive=20s;
+    open_file_cache_valid 60s;
+    open_file_cache_min_uses 5;
+    open_file_cache_errors off;
+
+    # Compression settings
+    gzip on;
+    gzip_comp_level 6;
+    gzip_min_length 256;
+    gzip_proxied any;
+    gzip_vary on;
+    gzip_types
+        application/javascript
+        application/json
+        application/x-javascript
+        application/xml
+        text/css
+        text/javascript
+        text/plain
+        text/xml
+        text/html
+        application/x-font-ttf
+        font/opentype
+        application/vnd.ms-fontobject
+        image/svg+xml;
 
     resolver 127.0.0.11 ipv6=off;
 
-    #gzip  on;
-
     server {
         listen       80;
         server_name  localhost;
 
-        #charset koi8-r;
-
-        #access_log  logs/host.access.log  main;
-
         location ^~ /api/ {
             proxy_set_header Host $host;
             proxy_set_header X-Real-IP $remote_addr;
             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
             proxy_set_header X-Forwarded-Proto $scheme;
+
+            # Proxy timeouts
+            proxy_connect_timeout 60s;
+            proxy_send_timeout 60s;
+            proxy_read_timeout 60s;
+            
+            # Proxy buffering
+            proxy_buffering on;
+            proxy_buffer_size 4k;
+            proxy_buffers 8 16k;
             
             # CORS headers
             add_header 'Access-Control-Allow-Origin' '*' always;
@@ -74,59 +105,23 @@ http {
             try_files $uri $uri/ /index.html;
         }
 
-        location ~* \.(js|css|jpg|png|svg|woff|woff2|ttf|otf|eot|ico)$ {
+
+        # Static asset handling with improved caching
+        location ~* \.(js|css|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|otf|eot)$ {
             root /usr/share/nginx/html;
-            add_header 'Access-Control-Allow-Origin' '*' always;
             expires 30d;
-            add_header Cache-Control "public";
+            add_header Cache-Control "public, no-transform";
+            add_header 'Access-Control-Allow-Origin' '*' always;
+            
+            # Enable compression for these files
+            gzip_static on;  # Serve pre-compressed files if available
+            
+            # Disable access logs for static files
+            access_log off;
         }
-
-        # #error_page  404              /404.html;
-
-        # # redirect server error pages to the static page /50x.html
-        # #
-        # error_page   500 502 503 504  /50x.html;
-        # location = /50x.html {
-        #     root   html;
-        # }
-
-        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
-        #
-        #location ~ \.php$ {
-        #    proxy_pass   http://127.0.0.1;
-        #}
-
-        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
-        #
-        #location ~ \.php$ {
-        #    root           html;
-        #    fastcgi_pass   127.0.0.1:9000;
-        #    fastcgi_index  index.php;
-        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
-        #    include        fastcgi_params;
-        #}
-
-        # deny access to .htaccess files, if Apache's document root
-        # concurs with nginx's one
-        #
-        #location ~ /\.ht {
-        #    deny  all;
-        #}
     }
 
 
-    # another virtual host using mix of IP-, name-, and port-based configuration
-    #
-    #server {
-    #    listen       8000;
-    #    listen       somename:8080;
-    #    server_name  somename  alias  another.alias;
-
-    #    location / {
-    #        root   html;
-    #        index  index.html index.htm;
-    #    }
-    #}
 
 
     # HTTPS server
@@ -149,5 +144,4 @@ http {
     #        index  index.html index.htm;
     #    }
     #}
-
 }
\ No newline at end of file
diff --git a/react-ui/package.json b/react-ui/package.json
index 4c9271009..5767007a1 100755
--- a/react-ui/package.json
+++ b/react-ui/package.json
@@ -13,6 +13,7 @@
         "@fortawesome/free-solid-svg-icons": "^6.6.0",
         "@fortawesome/react-fontawesome": "^0.2.2",
         "@reduxjs/toolkit": "^2.2.4",
+        "@vitejs/plugin-react": "^4.2.1",
         "bootstrap": "^5.3.3",
         "dompurify": "^3.2.3",
         "i18next": "^24.0.5",
@@ -24,11 +25,40 @@
         "react-i18next": "^15.0.0",
         "react-redux": "^9.1.2",
         "react-router-dom": "^6.23.1",
-        "react-scripts": "5.0.1",
         "react-toastify": "^10.0.5",
         "redux": "^5.0.1",
         "redux-observable": "^3.0.0-rc.2",
         "redux-persist": "^6.0.0",
+        "sass": "1.82.0",
+        "sass-embedded": "^1.80.6",
+        "@fullhuman/postcss-purgecss": "^7.0.2",
+        "vite": "^6.0.3"
+    },
+    "devDependencies": {
+        "@babel/runtime": "^7.21.5",
+        "@rtk-query/codegen-openapi": "^2.0.0",
+        "@testing-library/jest-dom": "^6.4.8",
+        "@testing-library/react": "^16.0.0",
+        "@testing-library/user-event": "^14.5.2",
+        "@types/react": "^18.2.66",
+        "@types/react-dom": "^18.2.22",
+        "@typescript-eslint/eslint-plugin": "^8.0.1",
+        "@typescript-eslint/parser": "^8.0.1",
+        "eslint": "^9.9.0",
+        "eslint-config-airbnb-typescript": "^18.0.0",
+        "eslint-config-prettier": "^9.1.0",
+        "eslint-plugin-import": "^2.27.5",
+        "eslint-plugin-jsx-a11y": "^6.7.1",
+        "eslint-plugin-prettier": "^5.2.1",
+        "eslint-plugin-react": "^7.32.2",
+        "eslint-plugin-react-hooks": "^5.1.0-rc.0",
+        "eslint-plugin-react-refresh": "^0.4.9",
+        "globals": "^15.9.0",
+        "prettier": "^3.3.3",
+        "react-scripts": "5.0.1",
+        "typescript": "^5.5.3",
+        "typescript-eslint": "^8.0.1",
+        "vite-bundle-visualizer": "^1.2.1",
         "web-vitals": "^4.2.2"
     },
     "scripts": {
@@ -38,7 +68,8 @@
         "build": "yarn build::api && yarn build::frontend",
         "lint": "eslint src",
         "lint::fix": "eslint src --fix",
-        "dev": "./scripts/dev.sh"
+        "dev": "./scripts/dev.sh",
+        "postbuild": "purgecss --css dist/assets/*.css --content dist/index.html dist/assets/*.js --output dist/purged"
     },
     "eslintConfig": {
         "extends": [
@@ -56,34 +87,5 @@
             "last 1 firefox version",
             "last 1 safari version"
         ]
-    },
-    "devDependencies": {
-        "@babel/runtime": "^7.21.5",
-        "@rtk-query/codegen-openapi": "^2.0.0",
-        "@testing-library/jest-dom": "^6.4.8",
-        "@testing-library/react": "^16.0.0",
-        "@testing-library/user-event": "^14.5.2",
-        "@types/react": "^18.2.66",
-        "@types/react-dom": "^18.2.22",
-        "@typescript-eslint/eslint-plugin": "^8.0.1",
-        "@typescript-eslint/parser": "^8.0.1",
-        "@vitejs/plugin-react": "^4.2.1",
-        "eslint": "^9.9.0",
-        "eslint-config-airbnb-typescript": "^18.0.0",
-        "eslint-config-prettier": "^9.1.0",
-        "eslint-plugin-import": "^2.27.5",
-        "eslint-plugin-jsx-a11y": "^6.7.1",
-        "eslint-plugin-prettier": "^5.2.1",
-        "eslint-plugin-react": "^7.32.2",
-        "eslint-plugin-react-hooks": "^5.1.0-rc.0",
-        "eslint-plugin-react-refresh": "^0.4.9",
-        "globals": "^15.9.0",
-        "prettier": "^3.3.3",
-        "sass": "1.82.0",
-        "sass-embedded": "^1.80.6",
-        "typescript": "^5.5.3",
-        "typescript-eslint": "^8.0.1",
-        "vite": "^6.0.3",
-        "vite-bundle-visualizer": "^1.2.1"
     }
 }
\ No newline at end of file
diff --git a/react-ui/public/fonts/inter-webfont.woff b/react-ui/public/fonts/inter-webfont.woff
new file mode 100644
index 0000000000000000000000000000000000000000..7eca6fe75d3ba56e14981e8f8e1c50d948bb8b56
GIT binary patch
literal 26796
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

literal 0
HcmV?d00001

diff --git a/react-ui/public/fonts/inter-webfont.woff2 b/react-ui/public/fonts/inter-webfont.woff2
new file mode 100644
index 0000000000000000000000000000000000000000..25ef870d53d5616ee3e92bbe3e85b5ed164fe4d2
GIT binary patch
literal 21204
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
Q-fa1H`MqE#XV7g%0OKi>>Hq)$

literal 0
HcmV?d00001

diff --git a/react-ui/src/components/devices/view/device.view.tsx b/react-ui/src/components/devices/view/device.view.tsx
index 2602463bb..a2c8458a7 100755
--- a/react-ui/src/components/devices/view/device.view.tsx
+++ b/react-ui/src/components/devices/view/device.view.tsx
@@ -6,7 +6,7 @@ import './device.scss';
 import { DeviceViewTable } from './device.view.table';
 import { DeviceViewTabs, DeviceViewTabValues } from './device.view.tabs';
 
-function DeviceView() {
+const DeviceView = () => {
     const { t } = useTranslation('common');
     const searchRef = useRef<HTMLInputElement>(null);
     const { activeTab, setActiveTab, handleActiveTabLink } = useDeviceViewModel();
diff --git a/react-ui/src/components/login/layouts/login.layout.tsx b/react-ui/src/components/login/layouts/login.layout.tsx
index 556dc6de4..58e8fc991 100755
--- a/react-ui/src/components/login/layouts/login.layout.tsx
+++ b/react-ui/src/components/login/layouts/login.layout.tsx
@@ -20,4 +20,6 @@ export const LoginLayout = () => {
     return (
         <LoginView>{outlet}</LoginView>
     )
-}
\ No newline at end of file
+}
+
+export default LoginLayout
\ No newline at end of file
diff --git a/react-ui/src/routes.tsx b/react-ui/src/routes.tsx
index 368df55a4..532d03fbf 100755
--- a/react-ui/src/routes.tsx
+++ b/react-ui/src/routes.tsx
@@ -1,21 +1,43 @@
 import { BasicLayout } from "@layout/basic.layout";
 import { ProtectedLayout } from "@layout/protected.layout/protected.layout";
+import { lazy, Suspense } from 'react';
 import { createBrowserRouter, createRoutesFromElements, Navigate, Route } from "react-router-dom";
-import DeviceView from "./components/devices/view/device.view";
-import { LoginLayout } from "./components/login/layouts/login.layout";
 
 export const DEVICE_URL = '/device/';
 export const LOGIN_URL = '/login';
 
+// Lazy load components
+const DeviceView = lazy(() => import('./components/devices/view/device.view'));
+const LoginLayout = lazy(() => import('./components/login/layouts/login.layout'));
+
+// Loading fallback component
+const LoadingFallback = () => <div>Loading...</div>;
 
 export const router = createBrowserRouter(
     createRoutesFromElements(
         <Route element={<BasicLayout />}>
-            <Route path={LOGIN_URL} element={<LoginLayout />} />
+            <Route
+                path={LOGIN_URL}
+                element={
+                    <Suspense fallback={<LoadingFallback />}>
+                        <LoginLayout />
+                    </Suspense>
+                }
+            />
             <Route element={<ProtectedLayout />}>
-                <Route path={DEVICE_URL} element={<DeviceView />} />
-                <Route path="/" element={<Navigate to={DEVICE_URL} replace={true} />} />
+                <Route
+                    path={DEVICE_URL}
+                    element={
+                        <Suspense fallback={<LoadingFallback />}>
+                            <DeviceView />
+                        </Suspense>
+                    }
+                />
+                <Route
+                    path="/"
+                    element={<Navigate to={DEVICE_URL} replace={true} />}
+                />
             </Route>
         </Route>
     )
-)
\ No newline at end of file
+);
\ No newline at end of file
diff --git a/react-ui/src/shared/icons/icons.ts b/react-ui/src/shared/icons/icons.ts
index 00021aa11..9c8791cc9 100755
--- a/react-ui/src/shared/icons/icons.ts
+++ b/react-ui/src/shared/icons/icons.ts
@@ -1,4 +1,4 @@
 import { library } from '@fortawesome/fontawesome-svg-core'
-import { faSpinner, fas } from '@fortawesome/free-solid-svg-icons'
+import { faSpinner } from '@fortawesome/free-solid-svg-icons'
 
-library.add(fas, faSpinner)
\ No newline at end of file
+library.add(faSpinner)
\ No newline at end of file
diff --git a/react-ui/src/shared/style/fonts.scss b/react-ui/src/shared/style/fonts.scss
index c47d1a52f..3af44e155 100755
--- a/react-ui/src/shared/style/fonts.scss
+++ b/react-ui/src/shared/style/fonts.scss
@@ -1,9 +1,12 @@
 @font-face {
     font-family: Inter;
-    src: url("/fonts/Inter.ttf");
+    src:
+        url("/fonts/inter-webfont.woff2") format("woff2"),
+        url("/fonts/inter-webfont.woff") format("woff");
+    font-weight: normal;
+    font-style: normal;
 }
 
-
 * {
     font-family: Inter;
-}
\ No newline at end of file
+}
diff --git a/react-ui/vite.config.mjs b/react-ui/vite.config.mjs
index fc4ce4a01..83378d6ee 100755
--- a/react-ui/vite.config.mjs
+++ b/react-ui/vite.config.mjs
@@ -1,13 +1,35 @@
-import react from '@vitejs/plugin-react'
-import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react';
+import { defineConfig } from 'vite';
+
 
 export default defineConfig({
     plugins: [react()],
     build: {
-        sourcemap: true,
+        sourcemap: false,
+
+        rollupOptions: {
+            output: {
+                manualChunks: {
+                    'required': [
+                        'bootstrap', 'react-bootstrap',
+                        'react', 'react-dom', 'react-router-dom',
+                        'redux', '@reduxjs/toolkit', 'react-redux', 'redux-observable', 'redux-persist',
+                        'i18next', 'react-i18next',
+                        '@fortawesome/fontawesome-svg-core',
+                        '@fortawesome/free-regular-svg-icons',
+                        '@fortawesome/free-solid-svg-icons',
+                        '@fortawesome/react-fontawesome'
+                    ],
+                    'lazy': [
+                        'react-toastify'
+                    ]
+                }
+            }
+        }
     },
     // develop server
     server: {
+        sourcemap: true,
         host: true,
         port: 3000,
         proxy: {
diff --git a/react-ui/yarn.lock b/react-ui/yarn.lock
index d054db6d6..62e8d8fa1 100755
--- a/react-ui/yarn.lock
+++ b/react-ui/yarn.lock
@@ -1486,6 +1486,13 @@
   dependencies:
     prop-types "^15.8.1"
 
+"@fullhuman/postcss-purgecss@^7.0.2":
+  version "7.0.2"
+  resolved "https://registry.yarnpkg.com/@fullhuman/postcss-purgecss/-/postcss-purgecss-7.0.2.tgz#ccacdbc312248c76c42cfac359f4ca5121001e67"
+  integrity sha512-U4zAXNaVztbDxO9EdcLp51F3UxxYsb/7DN89rFxFJhfk2Wua2pvw2Kf3HdspbPhW/wpHjSjsxWYoIlbTgRSjbQ==
+  dependencies:
+    purgecss "^7.0.2"
+
 "@humanfs/core@^0.19.1":
   version "0.19.1"
   resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77"
@@ -3906,6 +3913,11 @@ combined-stream@^1.0.8:
   dependencies:
     delayed-stream "~1.0.0"
 
+commander@^12.1.0:
+  version "12.1.0"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3"
+  integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==
+
 commander@^2.20.0:
   version "2.20.3"
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
@@ -5690,6 +5702,18 @@ glob@^10.3.10:
     package-json-from-dist "^1.0.0"
     path-scurry "^1.11.1"
 
+glob@^11.0.0:
+  version "11.0.0"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-11.0.0.tgz#6031df0d7b65eaa1ccb9b29b5ced16cea658e77e"
+  integrity sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==
+  dependencies:
+    foreground-child "^3.1.0"
+    jackspeak "^4.0.1"
+    minimatch "^10.0.0"
+    minipass "^7.1.2"
+    package-json-from-dist "^1.0.0"
+    path-scurry "^2.0.0"
+
 glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
   version "7.2.3"
   resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
@@ -6469,6 +6493,13 @@ jackspeak@^3.1.2:
   optionalDependencies:
     "@pkgjs/parseargs" "^0.11.0"
 
+jackspeak@^4.0.1:
+  version "4.0.2"
+  resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-4.0.2.tgz#11f9468a3730c6ff6f56823a820d7e3be9bef015"
+  integrity sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==
+  dependencies:
+    "@isaacs/cliui" "^8.0.2"
+
 jake@^10.8.5:
   version "10.9.2"
   resolved "https://registry.yarnpkg.com/jake/-/jake-10.9.2.tgz#6ae487e6a69afec3a5e167628996b59f35ae2b7f"
@@ -7277,6 +7308,11 @@ lru-cache@^10.2.0:
   resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119"
   integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==
 
+lru-cache@^11.0.0:
+  version "11.0.2"
+  resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.0.2.tgz#fbd8e7cf8211f5e7e5d91905c415a3f55755ca39"
+  integrity sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==
+
 lru-cache@^5.1.1:
   version "5.1.1"
   resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
@@ -7407,6 +7443,13 @@ minimalistic-assert@^1.0.0:
   resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
   integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
 
+minimatch@^10.0.0:
+  version "10.0.1"
+  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.0.1.tgz#ce0521856b453c86e25f2c4c0d03e6ff7ddc440b"
+  integrity sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==
+  dependencies:
+    brace-expansion "^2.0.1"
+
 minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
   version "3.1.2"
   resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
@@ -7923,6 +7966,14 @@ path-scurry@^1.11.1:
     lru-cache "^10.2.0"
     minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
 
+path-scurry@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-2.0.0.tgz#9f052289f23ad8bf9397a2a0425e7b8615c58580"
+  integrity sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==
+  dependencies:
+    lru-cache "^11.0.0"
+    minipass "^7.1.2"
+
 path-to-regexp@0.1.12:
   version "0.1.12"
   resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz#d5e1a12e478a976d432ef3c58d534b9923164bb7"
@@ -8653,6 +8704,16 @@ punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.1:
   resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
   integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
 
+purgecss@^7.0.2:
+  version "7.0.2"
+  resolved "https://registry.yarnpkg.com/purgecss/-/purgecss-7.0.2.tgz#b7dccc3ead65a4301eed98e014793719a511c633"
+  integrity sha512-4Ku8KoxNhOWi9X1XJ73XY5fv+I+hhTRedKpGs/2gaBKU8ijUiIKF/uyyIyh7Wo713bELSICF5/NswjcuOqYouQ==
+  dependencies:
+    commander "^12.1.0"
+    glob "^11.0.0"
+    postcss "^8.4.47"
+    postcss-selector-parser "^6.1.2"
+
 q@^1.1.2:
   version "1.5.1"
   resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
-- 
GitLab


From 431c22efbbae886e1cc9a068e0360e45b3882083 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Thu, 9 Jan 2025 08:07:16 +0000
Subject: [PATCH 23/79] [renovate] Update github.com/aristanetworks/goarista
 digest to 362a04c

See merge request danet/gosdn!1149

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 2 +-
 go.sum | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/go.mod b/go.mod
index 1946630f6..d7343eca0 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module code.fbi.h-da.de/danet/gosdn
 go 1.23
 
 require (
-	github.com/aristanetworks/goarista v0.0.0-20241115153057-bd75d7f26a44
+	github.com/aristanetworks/goarista v0.0.0-20250108214730-362a04c9d029
 	github.com/c-bata/go-prompt v0.2.6
 	github.com/docker/docker v24.0.9+incompatible
 	github.com/google/go-cmp v0.6.0
diff --git a/go.sum b/go.sum
index fe429b64a..83ec9b6c1 100644
--- a/go.sum
+++ b/go.sum
@@ -60,6 +60,8 @@ github.com/aristanetworks/goarista v0.0.0-20241101122619-a6d58bf1ed81 h1:CpeoPCo
 github.com/aristanetworks/goarista v0.0.0-20241101122619-a6d58bf1ed81/go.mod h1:C+YeQrhbMvCPh5wG6iqGiCD/zcITTpt4YQ1v4K0g5Vc=
 github.com/aristanetworks/goarista v0.0.0-20241115153057-bd75d7f26a44 h1:vb3HPPa1CegMZY90JF8mDyxXiV+qJJuSWwMhBZCcsws=
 github.com/aristanetworks/goarista v0.0.0-20241115153057-bd75d7f26a44/go.mod h1:C+YeQrhbMvCPh5wG6iqGiCD/zcITTpt4YQ1v4K0g5Vc=
+github.com/aristanetworks/goarista v0.0.0-20250108214730-362a04c9d029 h1:bvw2TILeXtuYfZ9rip/4DY933UuIvCwtvJmwvz978ac=
+github.com/aristanetworks/goarista v0.0.0-20250108214730-362a04c9d029/go.mod h1:C+YeQrhbMvCPh5wG6iqGiCD/zcITTpt4YQ1v4K0g5Vc=
 github.com/aristanetworks/gomap v0.0.0-20240724180630-b4cffb90720f h1:3GwV1IeLp0PwWcnbc9ZihE3osvexJf3PMjWSCGjtIqc=
 github.com/aristanetworks/gomap v0.0.0-20240724180630-b4cffb90720f/go.mod h1:bNzH6HFWav8D/ws3QlkjLpf9ZOdsUTDx+qJikWCcGRc=
 github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk=
-- 
GitLab


From 2d6e31d405b6f326db5a0f2cae53b9181350fcaa Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Thu, 9 Jan 2025 08:16:26 +0000
Subject: [PATCH 24/79] [renovate] Update module golang.org/x/crypto to v0.32.0

See merge request danet/gosdn!1150

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 6 +++---
 go.sum | 6 ++++++
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/go.mod b/go.mod
index d7343eca0..7c8225cdc 100644
--- a/go.mod
+++ b/go.mod
@@ -77,10 +77,10 @@ require (
 	github.com/xdg-go/stringprep v1.0.4 // indirect
 	github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
 	github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
-	golang.org/x/crypto v0.31.0
+	golang.org/x/crypto v0.32.0
 	golang.org/x/net v0.33.0
-	golang.org/x/sys v0.28.0 // indirect
-	golang.org/x/term v0.27.0 // indirect
+	golang.org/x/sys v0.29.0 // indirect
+	golang.org/x/term v0.28.0 // indirect
 	golang.org/x/text v0.21.0 // indirect
 	gopkg.in/ini.v1 v1.67.0 // indirect
 )
diff --git a/go.sum b/go.sum
index 83ec9b6c1..eb454ef9b 100644
--- a/go.sum
+++ b/go.sum
@@ -423,6 +423,8 @@ golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY=
 golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
 golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
 golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
+golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
+golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7 h1:wDLEX9a7YQoKdKNQt88rtydkqDxeGaBUTnIYc3iG/mA=
 golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
@@ -517,6 +519,8 @@ golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
 golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
 golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
+golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -530,6 +534,8 @@ golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
 golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
 golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
 golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
+golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
+golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-- 
GitLab


From 7dfa8398f470c6e53934c5c07298f20b6ff9da2f Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@@stud.h-da.de>
Date: Thu, 9 Jan 2025 13:17:49 +0100
Subject: [PATCH 25/79] (ui): reduced complexity of rehydration process

---
 .../devices/reducer/device.reducer.ts         | 58 +++++++++++++++----
 .../devices/routines/device.routine.ts        |  2 +-
 .../devices/routines/mne.routine.ts           | 12 ++--
 .../view_model/device.table.viewmodel.ts      |  2 +-
 react-ui/src/index.tsx                        |  8 ---
 .../src/shared/reducer/routine.reducer.ts     | 35 +++--------
 react-ui/src/shared/types/thunk.type.ts       | 15 +----
 .../shared/utils/routine-holder.singleton.ts  | 47 ---------------
 8 files changed, 65 insertions(+), 114 deletions(-)
 delete mode 100644 react-ui/src/shared/utils/routine-holder.singleton.ts

diff --git a/react-ui/src/components/devices/reducer/device.reducer.ts b/react-ui/src/components/devices/reducer/device.reducer.ts
index 4afcba788..cea12fbc9 100755
--- a/react-ui/src/components/devices/reducer/device.reducer.ts
+++ b/react-ui/src/components/devices/reducer/device.reducer.ts
@@ -5,6 +5,7 @@ import {
 } from '@api/api'
 import { DeviceViewTabValues } from '@component/devices/view/device.view.tabs'
 import { createSlice, PayloadAction } from '@reduxjs/toolkit'
+import { REHYDRATE } from 'redux-persist'
 import { RootState } from 'src/stores'
 import '../routines/index'
 import { startListening } from '/src/stores/middleware/listener.middleware'
@@ -32,6 +33,13 @@ const initialState: DeviceSliceState = {
     selected: null,
 }
 
+interface SetSelectedDeviceType {
+    device: Device | null,
+    options?: {
+        bypassCheck: boolean
+    }
+}
+
 const deviceSlice = createSlice({
     name: 'device',
     initialState,
@@ -46,24 +54,33 @@ const deviceSlice = createSlice({
             state.activeTab = action.payload
         },
         setSelectedDevice: {
-            reducer: (state, action: PayloadAction<Device | null, string, { skipListener?: boolean }>) => {
-                // do thing if desired device is already selected
-                if (state.selected?.device.id === action.payload?.id) {
-                    action.meta.skipListener = true
+            reducer: (state, { payload, meta }: PayloadAction<SetSelectedDeviceType, string, { skipListener?: boolean }>) => {
+                /**
+                 * Do nothing if desired device is already selected
+                 * Bypass the check if the flag is set to true. We
+                 * use this bypass to trigger the listener functions
+                 * accordingly
+                 */
+                if (!payload?.options?.bypassCheck && state.selected?.device.id === payload.device?.id) {
+                    meta.skipListener = true
                     return
                 }
 
-                let selectedObject = null;
-                if (action.payload) {
-                    selectedObject = { device: action.payload, mne: null, json: null }
+                if (!payload.device) {
+                    throw Error('Passed null device as parameter while bypassing the safety check')
+                }
+
+                let selectedObject: SelectedObject | null = null;
+                if (payload) {
+                    selectedObject = { device: payload.device, mne: null, json: null }
                 }
 
                 state.selected = selectedObject
             },
-            prepare: (device: Device | null) => {
+            prepare: (payload) => {
                 return {
-                    payload: device,
-                    meta: { skipListener: false } // set to true when needed
+                    payload,
+                    meta: { skipListener: false }
                 }
             }
         },
@@ -107,7 +124,24 @@ startListening({
         }
 
         // if there are no devices available do set null
-        const newDevices = action.payload?.[0] || null
-        listenerApi.dispatch(setSelectedDevice(newDevices))
+        const device = action.payload?.[0] || null
+        listenerApi.dispatch(setSelectedDevice({ device } as SetSelectedDeviceType))
     },
 })
+
+
+/**
+ * On startup reset the selected device 
+ */
+startListening({
+    predicate: ({ type }: any) => type === REHYDRATE,
+    effect: async (_, listenerApi) => {
+        const { device: state } = listenerApi.getState() as RootState
+        const device = state.selected?.device
+        if (!device) {
+            return
+        }
+
+        listenerApi.dispatch(setSelectedDevice({ device, options: { bypassCheck: true } } as SetSelectedDeviceType))
+    },
+})
\ No newline at end of file
diff --git a/react-ui/src/components/devices/routines/device.routine.ts b/react-ui/src/components/devices/routines/device.routine.ts
index f9b3e1ee2..ef92b1c8e 100755
--- a/react-ui/src/components/devices/routines/device.routine.ts
+++ b/react-ui/src/components/devices/routines/device.routine.ts
@@ -20,7 +20,7 @@ export const fetchDevicesThunk = createAsyncThunk(FETCH_DEVICE_ACTION, (_, thunk
     const { user } = thunkApi.getState() as RootState
 
     if (!user.user?.roles) {
-        throw new Error('Background MNE fetching failed! User data is missing. Reload page or logout and login again')
+        throw new Error('Background device fetching failed! User data is missing. Reload page or logout and login again')
         // TODO
     }
 
diff --git a/react-ui/src/components/devices/routines/mne.routine.ts b/react-ui/src/components/devices/routines/mne.routine.ts
index 876317dd2..292869307 100755
--- a/react-ui/src/components/devices/routines/mne.routine.ts
+++ b/react-ui/src/components/devices/routines/mne.routine.ts
@@ -8,12 +8,12 @@ import {
 import { createAsyncThunk } from '@reduxjs/toolkit'
 import { addRoutine } from '@shared/reducer/routine.reducer'
 import { Category, CategoryType } from '@shared/types/category.type'
-import { RoutineHolderSingleton } from '@utils/routine-holder.singleton'
 import { RootState } from 'src/stores'
 import { startListening } from '../../../stores/middleware/listener.middleware'
 
 export const FETCH_MNE_ACTION = 'subscription/device/fetchSelectedMNE'
 
+
 /**
  * #0
  * Trigger fetch MNE (#1)
@@ -21,14 +21,16 @@ export const FETCH_MNE_ACTION = 'subscription/device/fetchSelectedMNE'
  * Triggered by a selectedDevice
  */
 startListening({
-    predicate: (action) => setSelectedDevice.match(action) && !!action.payload && !action.meta?.skipListener,
+    predicate: (action) => setSelectedDevice.match(action) && !!action.payload.device && !action.meta?.skipListener,
     effect: async (action, listenerApi) => {
-        const factory = RoutineHolderSingleton.getInstance();
+
+        const device = action.payload.device
+
         listenerApi.dispatch(
             addRoutine({
-                thunk: factory.getRoutineByName("fetchSelectedMneThunk"),
+                thunk: fetchSelectedMneThunk,
                 category: Category.TAB as CategoryType,
-                payload: action.payload as Object,
+                payload: device,
             })
         )
     },
diff --git a/react-ui/src/components/devices/view_model/device.table.viewmodel.ts b/react-ui/src/components/devices/view_model/device.table.viewmodel.ts
index df7595328..5769780ff 100755
--- a/react-ui/src/components/devices/view_model/device.table.viewmodel.ts
+++ b/react-ui/src/components/devices/view_model/device.table.viewmodel.ts
@@ -26,7 +26,7 @@ export const useDeviceTableViewModel = (searchRef) => {
     }, []);
 
     const trClickHandler = (device: Device) => {
-        dispatch(setSelectedDevice(device));
+        dispatch(setSelectedDevice({ device }));
     }
 
 
diff --git a/react-ui/src/index.tsx b/react-ui/src/index.tsx
index 559e1bc54..3697efd07 100755
--- a/react-ui/src/index.tsx
+++ b/react-ui/src/index.tsx
@@ -1,6 +1,4 @@
-import { fetchSelectedMneThunk } from '@component/devices/routines/mne.routine'
 import { UtilsProvider } from '@provider/utils.provider'
-import { RoutineHolderSingleton } from '@utils/routine-holder.singleton'
 import i18next from 'i18next'
 import React from 'react'
 import ReactDOM from 'react-dom/client'
@@ -20,12 +18,6 @@ import { persistor, store } from './stores'
 
 window.env = window.location.hostname === 'localhost' ? 'development' : 'production';
 
-const factory = RoutineHolderSingleton.getInstance();
-factory.registerRoutine("fetchSelectedMneThunk", {
-    func: fetchSelectedMneThunk,
-    id: 0
-});
-
 ReactDOM.createRoot(document.getElementById("root")).render(
     <React.StrictMode>
         <ErrorBoundary fallback={<div>Something went wrong</div>}>
diff --git a/react-ui/src/shared/reducer/routine.reducer.ts b/react-ui/src/shared/reducer/routine.reducer.ts
index f8c8c31eb..5e9c3401a 100755
--- a/react-ui/src/shared/reducer/routine.reducer.ts
+++ b/react-ui/src/shared/reducer/routine.reducer.ts
@@ -1,9 +1,7 @@
 import { PayloadAction, createSlice } from '@reduxjs/toolkit'
 import { CategoryType } from '@shared/types/category.type'
 import { ThunkDTO, ThunkPersist } from '@shared/types/thunk.type'
-import { RoutineHolderSingleton } from '@utils/routine-holder.singleton'
 import { RoutineManager } from '@utils/routine.manager'
-import { REHYDRATE } from 'redux-persist'
 import { RootState } from '../../stores'
 import { startListening } from '../../stores/middleware/listener.middleware'
 import { setToken } from './user.reducer'
@@ -52,30 +50,6 @@ startListening({
     },
 })
 
-// on rehydrate add all persistet routines
-// TODO -> thunk does not have the thunk function object due to its coming from the store that ignores the value.
-// at this point we have to figure out how to get the thunk function out of the "string" name
-startListening({
-    predicate: ({ type }) => type === REHYDRATE,
-    effect: async (_, listenerApi) => {
-        const { routine } = listenerApi.getState() as RootState
-        const routines = RoutineHolderSingleton.getInstance()
-
-        Object.values(routine.thunks)
-            .filter(thunk => !!thunk)
-            .forEach(thunk => {
-                const container = routines.getRoutineById(thunk.thunkId)
-                const dto: ThunkDTO = {
-                    category: thunk.category,
-                    payload: thunk.payload,
-                    thunk: container
-                }
-
-                listenerApi.dispatch(addRoutine(dto))
-            })
-    },
-})
-
 /**
  * Add new routine
  * 
@@ -87,12 +61,17 @@ startListening({
     predicate: (action) => addRoutine.match(action),
     effect: async (action, listenerApi) => {
         const { thunk } = action.payload as ThunkDTO
-        const subscription = await listenerApi.dispatch(thunk.func(action.payload.payload))
+        const subscription = await listenerApi.dispatch(thunk(action.payload.payload))
+
+        if (subscription.error) {
+            throw new Error('Error during routine execution: ' + subscription.error.message)
+        }
+
         RoutineManager.add(subscription.payload, action.payload.category)
     },
 })
 
-// unsubscribe old routine
+// unsubscribe old routine that is in the same category
 startListening({
     predicate: (action) => addRoutine.match(action),
     effect: async (action, listenerApi) => {
diff --git a/react-ui/src/shared/types/thunk.type.ts b/react-ui/src/shared/types/thunk.type.ts
index 90b846039..9143871f0 100644
--- a/react-ui/src/shared/types/thunk.type.ts
+++ b/react-ui/src/shared/types/thunk.type.ts
@@ -1,21 +1,12 @@
 import { CategoryType } from "./category.type"
 
 
-/**
- * Contains the thunk function combined with a unique id
- * Giving a explicit id (and not the index of the object)
- * prevents missmatching the function if a update changes
- * the RoutineList object length 
- */
-export interface ThunkContainer {
-    id: number
-    func: any,
-}
+// The actual Thunk type is hard to determine because is very generic 
+export type ThunkFunc = any
 
 
 export interface ThunkDTO {
-    thunk: ThunkContainer
-
+    thunk: ThunkFunc
     payload: Object
 
     /**
diff --git a/react-ui/src/shared/utils/routine-holder.singleton.ts b/react-ui/src/shared/utils/routine-holder.singleton.ts
deleted file mode 100644
index 47332ab0b..000000000
--- a/react-ui/src/shared/utils/routine-holder.singleton.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import { ThunkContainer } from "@shared/types/thunk.type";
-
-interface LocalThunkContainer {
-    container: ThunkContainer,
-    name: string
-}
-
-export class RoutineHolderSingleton {
-    private static instance: RoutineHolderSingleton;
-    private routineList: Array<LocalThunkContainer> = []
-
-    private constructor() { }
-
-    static getInstance(): RoutineHolderSingleton {
-        if (!RoutineHolderSingleton.instance) {
-            RoutineHolderSingleton.instance = new RoutineHolderSingleton();
-        }
-        return RoutineHolderSingleton.instance;
-    }
-
-    registerRoutine(name: string, thunk: ThunkContainer) {
-        this.routineList = [...this.routineList, { container: thunk, name }];
-    }
-
-    getRoutineById(id: number): ThunkContainer {
-        const routine = this.routineList.find((thunk) => thunk.container.id === id)
-
-        if (!routine) {
-            throw new Error('')
-            // TODO
-        }
-
-        return routine.container;
-    }
-
-
-    getRoutineByName(name: string): ThunkContainer {
-        const routine = this.routineList.find((thunk) => thunk.name === name)
-
-        if (!routine) {
-            throw new Error('')
-            // TODO
-        }
-
-        return routine.container;
-    }
-}
\ No newline at end of file
-- 
GitLab


From eed9fbb5d2b2236a62d6dd0acf0a159c8310b35d Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@@stud.h-da.de>
Date: Thu, 9 Jan 2025 14:02:32 +0100
Subject: [PATCH 26/79] (ui): add highlight on search in table

---
 .../src/components/devices/api/pnd.fetch.ts   | 15 ----------
 .../devices/view/device.view.table.tsx        | 30 ++++++++++++-------
 .../json_viewer/view/json_viewer.view.tsx     |  8 +----
 react-ui/src/shared/helper/text.ts            | 12 ++++++++
 .../protected.layout/protected.layout.tsx     |  3 +-
 .../user.fetch.ts => routine/user.routine.ts} | 14 ++++++++-
 6 files changed, 46 insertions(+), 36 deletions(-)
 delete mode 100644 react-ui/src/components/devices/api/pnd.fetch.ts
 create mode 100644 react-ui/src/shared/helper/text.ts
 rename react-ui/src/shared/{api/user.fetch.ts => routine/user.routine.ts} (63%)

diff --git a/react-ui/src/components/devices/api/pnd.fetch.ts b/react-ui/src/components/devices/api/pnd.fetch.ts
deleted file mode 100644
index fd49de636..000000000
--- a/react-ui/src/components/devices/api/pnd.fetch.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { PndServiceGetPndListApiArg, api } from "@api/api"
-import { createAsyncThunk } from "@reduxjs/toolkit"
-import { setPnds } from "../reducer/device.reducer"
-
-// TODO rethink this. This should be in the shared part bc its getting invoked in the procteded layout
-export const fetchPnds = createAsyncThunk('device/fetchPnds', (_, thunkApi) => {
-    const payload: PndServiceGetPndListApiArg = {
-        timestamp: new Date().getTime().toString(),
-    }
-
-    const subscription = thunkApi.dispatch(api.endpoints.pndServiceGetPndList.initiate(payload))
-    subscription.unwrap().then((response) => {
-        thunkApi.dispatch(setPnds(response.pnd))
-    })
-})
\ No newline at end of file
diff --git a/react-ui/src/components/devices/view/device.view.table.tsx b/react-ui/src/components/devices/view/device.view.table.tsx
index 9b731fef5..337148f92 100755
--- a/react-ui/src/components/devices/view/device.view.table.tsx
+++ b/react-ui/src/components/devices/view/device.view.table.tsx
@@ -1,4 +1,6 @@
+import { insertMarkTags } from "@helper/text";
 import { useAppSelector } from "@hooks";
+import DOMPurify from 'dompurify';
 import { MutableRefObject, useCallback } from "react";
 import { OverlayTrigger, Table, Tooltip } from "react-bootstrap";
 import { useTranslation } from "react-i18next";
@@ -15,25 +17,30 @@ export const DeviceViewTable = (searchRef: MutableRefObject<HTMLInputElement>) =
     }
 
     const getDeviceTable = useCallback(() => {
-        return devices.filter((device) => {
-            if (!searchRef.current?.value) {
-                return true;
-            }
+        const search = searchRef.current?.value;
+        let filtered = devices
 
-            const searchInput = searchRef.current!.value;
-            const user = pnds.find(pnd => pnd.id === device.pid);
+        // filter if something is in search
+        if (search) {
+            filtered = devices.filter((device) => {
+                const user = pnds.find(pnd => pnd.id === device.pid);
+
+                return device.id?.includes(search) ||
+                    device.name?.includes(search) ||
+                    user?.name?.includes(search);
+            })
+        }
 
-            return device.id.includes(searchInput) || device.name.includes(searchInput) || user?.name.includes(searchInput);
-        }).map((device, index) => {
+        return filtered.map((device, index) => {
             const user = pnds.find(pnd => pnd.id === device.pid);
 
             return (
                 <tr key={index} onClick={() => trClickHandler(device)} className={selectedDevice?.device.id === device.id ? 'active' : ''}>
-                    <td>{device.name}</td>
+                    <td key={0} dangerouslySetInnerHTML={{ __html: search ? insertMarkTags(device.name!, search) : DOMPurify.sanitize(device.name) }}></td>
                     <OverlayTrigger overlay={<Tooltip id={device.id}>{device.id}</Tooltip>}>
-                        <td>{cropUUID(device.id)}</td>
+                        <td dangerouslySetInnerHTML={{ __html: search ? insertMarkTags(cropUUID(device.id!), search) : DOMPurify.sanitize(cropUUID(device.id!)) }}></td>
                     </OverlayTrigger>
-                    <td>{user?.name || ''}</td>
+                    <td key={1} dangerouslySetInnerHTML={{ __html: search ? insertMarkTags(user?.name || '', search) : DOMPurify.sanitize(user?.name || '') }}></td>
                     <td></td>
                 </tr>
             )
@@ -41,6 +48,7 @@ export const DeviceViewTable = (searchRef: MutableRefObject<HTMLInputElement>) =
     }, [devices, searchRef, pnds, selectedDevice, trClickHandler]);
 
 
+
     return (
         <Table striped responsive className="device-table">
             <thead>
diff --git a/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx b/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx
index b8358c686..33e52a397 100755
--- a/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx
+++ b/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx
@@ -1,5 +1,6 @@
 import { faAlignRight, faPenToSquare, faTrashCan } from "@fortawesome/free-solid-svg-icons"
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
+import { insertMarkTags } from "@helper/text"
 import DOMPurify from 'dompurify'
 import React, { Suspense, useMemo, useRef } from "react"
 import { Form, Table } from "react-bootstrap"
@@ -30,13 +31,6 @@ export const JsonViewer = ({ json }: JsonViewerProbs) => {
         )
     }, [breadcrumbs])
 
-    const insertMarkTags = (text: string, search: string): string => {
-        const start = text.indexOf(search)
-        const end = start + search.length
-
-        return DOMPurify.sanitize(text.substring(0, start)) + "<span class='highlight'>" + DOMPurify.sanitize(search) + "</span>" + DOMPurify.sanitize(text.substring(end, text.length))
-    }
-
     const renderInner = (innerJson: JSON, nested: number = 0, parentKey: string = "", path: string = "/network-instance/0/"): JSX.Element => {
         path += parentKey + (parentKey === "" ? "" : "/")
 
diff --git a/react-ui/src/shared/helper/text.ts b/react-ui/src/shared/helper/text.ts
new file mode 100644
index 000000000..6aee13790
--- /dev/null
+++ b/react-ui/src/shared/helper/text.ts
@@ -0,0 +1,12 @@
+
+import DOMPurify from 'dompurify'
+
+export const insertMarkTags = (text: string, search: string): string => {
+    const start = text.indexOf(search)
+    if (start === -1) {
+        return DOMPurify.sanitize(text)
+    }
+    const end = start + search.length
+
+    return DOMPurify.sanitize(text.substring(0, start)) + "<span class='highlight'>" + DOMPurify.sanitize(search) + "</span>" + DOMPurify.sanitize(text.substring(end, text.length))
+}
\ No newline at end of file
diff --git a/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx b/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx
index 17b6209a5..b017cf56f 100755
--- a/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx
+++ b/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx
@@ -1,12 +1,11 @@
-import { fetchUser } from '@api/user.fetch';
 import logo from '@assets/logo.svg';
-import { fetchPnds } from '@component/devices/api/pnd.fetch';
 import { faCircleUser, faRightFromBracket } from "@fortawesome/free-solid-svg-icons";
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { useAppDispatch, useAppSelector } from '@hooks';
 import { useAuth } from "@provider/auth.provider";
 import { MenuProvider } from '@provider/menu/menu.provider';
 import { DEVICE_URL, LOGIN_URL } from '@routes';
+import { fetchPnds, fetchUser } from '@shared/routine/user.routine';
 import React, { useEffect } from "react";
 import { Dropdown } from "react-bootstrap";
 import { useTranslation } from "react-i18next";
diff --git a/react-ui/src/shared/api/user.fetch.ts b/react-ui/src/shared/routine/user.routine.ts
similarity index 63%
rename from react-ui/src/shared/api/user.fetch.ts
rename to react-ui/src/shared/routine/user.routine.ts
index 08806783b..368ccf412 100644
--- a/react-ui/src/shared/api/user.fetch.ts
+++ b/react-ui/src/shared/routine/user.routine.ts
@@ -1,7 +1,8 @@
+import { api, PndServiceGetPndListApiArg, UserServiceGetUsersApiArg } from "@api/api"
+import { setPnds } from "@component/devices/reducer/device.reducer"
 import { createAsyncThunk } from "@reduxjs/toolkit"
 import { setUser } from "@shared/reducer/user.reducer"
 import { RootState } from "src/stores"
-import { api, UserServiceGetUsersApiArg } from "./api"
 
 export const fetchUser = createAsyncThunk('user/fetchUser', (_, thunkAPI) => {
     const payload: UserServiceGetUsersApiArg = {}
@@ -23,3 +24,14 @@ export const fetchUser = createAsyncThunk('user/fetchUser', (_, thunkAPI) => {
         thunkAPI.dispatch(setUser(matchedUser))
     })
 })
+
+export const fetchPnds = createAsyncThunk('device/fetchPnds', (_, thunkApi) => {
+    const payload: PndServiceGetPndListApiArg = {
+        timestamp: new Date().getTime().toString(),
+    }
+
+    const subscription = thunkApi.dispatch(api.endpoints.pndServiceGetPndList.initiate(payload))
+    subscription.unwrap().then((response) => {
+        thunkApi.dispatch(setPnds(response.pnd))
+    })
+})
\ No newline at end of file
-- 
GitLab


From 4585c77df111eca5d2430c146ab3d084be5b1e71 Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@@stud.h-da.de>
Date: Thu, 9 Jan 2025 18:35:57 +0100
Subject: [PATCH 27/79] (ui): add copy and copy row menu options

---
 react-ui/package.json                         |  5 +-
 .../devices/view/device.view.table.tsx        | 35 ++++----
 .../view_model/device.table.viewmodel.ts      | 84 +++++++++++++++++--
 .../src/i18n/locales/en/translations.json     |  7 +-
 .../viewmodel/json_viewer.viewmodel.tsx       | 45 +++++-----
 .../shared/provider/menu/menu.provider.tsx    | 43 ++++++----
 react-ui/yarn.lock                            |  5 ++
 7 files changed, 162 insertions(+), 62 deletions(-)

diff --git a/react-ui/package.json b/react-ui/package.json
index 5767007a1..30db7c97c 100755
--- a/react-ui/package.json
+++ b/react-ui/package.json
@@ -12,9 +12,11 @@
         "@fortawesome/free-regular-svg-icons": "^6.6.0",
         "@fortawesome/free-solid-svg-icons": "^6.6.0",
         "@fortawesome/react-fontawesome": "^0.2.2",
+        "@fullhuman/postcss-purgecss": "^7.0.2",
         "@reduxjs/toolkit": "^2.2.4",
         "@vitejs/plugin-react": "^4.2.1",
         "bootstrap": "^5.3.3",
+        "crypto-js": "^4.2.0",
         "dompurify": "^3.2.3",
         "i18next": "^24.0.5",
         "jwt-decode": "^4.0.0",
@@ -31,7 +33,6 @@
         "redux-persist": "^6.0.0",
         "sass": "1.82.0",
         "sass-embedded": "^1.80.6",
-        "@fullhuman/postcss-purgecss": "^7.0.2",
         "vite": "^6.0.3"
     },
     "devDependencies": {
@@ -88,4 +89,4 @@
             "last 1 safari version"
         ]
     }
-}
\ No newline at end of file
+}
diff --git a/react-ui/src/components/devices/view/device.view.table.tsx b/react-ui/src/components/devices/view/device.view.table.tsx
index 337148f92..56ad05f3f 100755
--- a/react-ui/src/components/devices/view/device.view.table.tsx
+++ b/react-ui/src/components/devices/view/device.view.table.tsx
@@ -1,20 +1,20 @@
 import { insertMarkTags } from "@helper/text";
 import { useAppSelector } from "@hooks";
 import DOMPurify from 'dompurify';
-import { MutableRefObject, useCallback } from "react";
+import { MutableRefObject, useCallback, useRef } from "react";
 import { OverlayTrigger, Table, Tooltip } from "react-bootstrap";
 import { useTranslation } from "react-i18next";
 import { useDeviceTableViewModel } from "../view_model/device.table.viewmodel";
 
+const cropUUID = (uuid: string): string => {
+    return uuid.substring(0, 3) + "..." + uuid.substring(uuid.length - 3, uuid.length);
+}
+
 export const DeviceViewTable = (searchRef: MutableRefObject<HTMLInputElement>) => {
     const { devices, pnds, selected: selectedDevice } = useAppSelector(state => state.device);
     const { t } = useTranslation('common');
-    const { trClickHandler } = useDeviceTableViewModel(searchRef);
-
-
-    const cropUUID = (uuid: string): string => {
-        return uuid.substring(0, 3) + "..." + uuid.substring(uuid.length - 3, uuid.length);
-    }
+    const tableRef = useRef();
+    const { trClickHandler } = useDeviceTableViewModel(searchRef, tableRef);
 
     const getDeviceTable = useCallback(() => {
         const search = searchRef.current?.value;
@@ -34,23 +34,28 @@ export const DeviceViewTable = (searchRef: MutableRefObject<HTMLInputElement>) =
         return filtered.map((device, index) => {
             const user = pnds.find(pnd => pnd.id === device.pid);
 
+            const username = user?.name || ''
+            const deviceId = device.id!;
+            const cropedId = cropUUID(deviceId)
+            const devicename = device.name || '';
+
+            const rowData = username + ";" + deviceId + ";" + devicename
+
             return (
-                <tr key={index} onClick={() => trClickHandler(device)} className={selectedDevice?.device.id === device.id ? 'active' : ''}>
-                    <td key={0} dangerouslySetInnerHTML={{ __html: search ? insertMarkTags(device.name!, search) : DOMPurify.sanitize(device.name) }}></td>
-                    <OverlayTrigger overlay={<Tooltip id={device.id}>{device.id}</Tooltip>}>
-                        <td dangerouslySetInnerHTML={{ __html: search ? insertMarkTags(cropUUID(device.id!), search) : DOMPurify.sanitize(cropUUID(device.id!)) }}></td>
+                <tr data-copy-value={rowData} key={index} onClick={() => trClickHandler(device)} className={selectedDevice?.device.id === deviceId ? 'active' : ''}>
+                    <td data-copy-value={devicename} dangerouslySetInnerHTML={{ __html: search ? insertMarkTags(devicename, search) : DOMPurify.sanitize(devicename) }}></td>
+                    <OverlayTrigger overlay={<Tooltip id={device.id}>{deviceId}</Tooltip>}>
+                        <td data-copy-value={deviceId} dangerouslySetInnerHTML={{ __html: search ? insertMarkTags(cropedId, search) : DOMPurify.sanitize(cropedId) }}></td>
                     </OverlayTrigger>
-                    <td key={1} dangerouslySetInnerHTML={{ __html: search ? insertMarkTags(user?.name || '', search) : DOMPurify.sanitize(user?.name || '') }}></td>
+                    <td data-copy-value={username} dangerouslySetInnerHTML={{ __html: search ? insertMarkTags(username, search) : DOMPurify.sanitize(username) }}></td>
                     <td></td>
                 </tr>
             )
         })
     }, [devices, searchRef, pnds, selectedDevice, trClickHandler]);
 
-
-
     return (
-        <Table striped responsive className="device-table">
+        <Table striped responsive className="device-table" ref={tableRef}>
             <thead>
                 <tr>
                     <th>{t('device.table.header.name')}</th>
diff --git a/react-ui/src/components/devices/view_model/device.table.viewmodel.ts b/react-ui/src/components/devices/view_model/device.table.viewmodel.ts
index 5769780ff..4b328d639 100755
--- a/react-ui/src/components/devices/view_model/device.table.viewmodel.ts
+++ b/react-ui/src/components/devices/view_model/device.table.viewmodel.ts
@@ -1,29 +1,97 @@
 import { Device, setSelectedDevice } from "@component/devices/reducer/device.reducer";
+import { faCopy } from "@fortawesome/free-solid-svg-icons";
 import { useAppDispatch } from "@hooks";
+import { useMenu } from "@provider/menu/menu.provider";
+import { useUtils } from "@provider/utils.provider";
 import { useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { toast } from "react-toastify";
 
-export const useDeviceTableViewModel = (searchRef) => {
+export const useDeviceTableViewModel = (searchRef, tableRef) => {
     const [searchTerm, setSearchTerm] = useState('');
     const dispatch = useAppDispatch();
+    const { subscribe } = useMenu();
+    const { toClipboard } = useUtils();
+    const { t } = useTranslation('common');
+
+
+    const registerMenuOptions = () => {
+        const subscription = subscribe({
+            target: tableRef.current,
+            actions: [
+                {
+                    key: t('device.table.actions.copy'),
+                    icon: faCopy,
+                    action: (clickedElement) => {
+                        if (clickedElement) {
+                            const text = clickedElement.dataset.copyValue
+                            if (!text) {
+                                toast.warn(t('global.toast.copied_failed'))
+                                return
+                            }
+
+
+                            toClipboard(text)
+                        }
+                    }
+                },
+
+                {
+                    key: t('device.table.actions.copy_row'),
+                    icon: faCopy,
+                    action: (clickedElement) => {
+                        let parent = clickedElement;
+                        while (parent && parent.tagName !== 'TR') {
+                            parent = parent.parentNode;
+                        }
+
+                        const text = parent.dataset.copyValue
+                        if (!text) {
+                            toast.warn(t('global.toast.copied_failed'))
+                            return
+                        }
+                        toClipboard(text)
+                    }
+                }
+            ]
+        })
+
+        return () => {
+            subscription.unsubscribe()
+        }
+    }
+
+    // seperate use effect to rerun this after tableref and subscribe are initialized
+    useEffect(() => {
+        if (!subscribe || !tableRef.current) {
+            return
+        }
+
+        const unsubscribe = registerMenuOptions()
+
+        return () => {
+            unsubscribe()
+        }
+    }, [tableRef, subscribe])
 
 
     useEffect(() => {
+        if (!searchRef.current) {
+            return
+        }
+
         const handleSearchChange = () => {
-            if (searchRef.current) {
-                setSearchTerm(searchRef.current.value);
-            }
+            setSearchTerm(searchRef.current.value);
         };
 
-        if (searchRef.current) {
-            searchRef.current.addEventListener('input', handleSearchChange);
-        }
+        searchRef.current.addEventListener('input', handleSearchChange);
 
         return () => {
             if (searchRef.current) {
                 searchRef.current.removeEventListener('input', handleSearchChange);
             }
         };
-    }, []);
+    }, [searchRef]);
 
     const trClickHandler = (device: Device) => {
         dispatch(setSelectedDevice({ device }));
diff --git a/react-ui/src/i18n/locales/en/translations.json b/react-ui/src/i18n/locales/en/translations.json
index 46b76563c..fb3ca729c 100755
--- a/react-ui/src/i18n/locales/en/translations.json
+++ b/react-ui/src/i18n/locales/en/translations.json
@@ -6,7 +6,8 @@
                 "empty_field": "This field can´t be empty"
             },
             "toast": {
-                "copied": "Copied to clipboard"
+                "copied": "Copied to clipboard",
+                "copied_failed": "Copying to clipboard failed"
             },
             "menu_item": {
                 "logout": "Logout"
@@ -35,6 +36,10 @@
                     "uuid": "UUID",
                     "user": "User",
                     "last_updated": "Last updated"
+                },
+                "actions": {
+                    "copy": "Copy",
+                    "copy_row": "Copy row"
                 }
             },
             "search": {
diff --git a/react-ui/src/shared/components/json_viewer/viewmodel/json_viewer.viewmodel.tsx b/react-ui/src/shared/components/json_viewer/viewmodel/json_viewer.viewmodel.tsx
index 6c3ac78f3..f0bc92212 100644
--- a/react-ui/src/shared/components/json_viewer/viewmodel/json_viewer.viewmodel.tsx
+++ b/react-ui/src/shared/components/json_viewer/viewmodel/json_viewer.viewmodel.tsx
@@ -67,29 +67,31 @@ export const useJsonViewer = ({ json, search, container }: JsonViewerViewModelTy
     }
 
     const registerMenuOptions = () => {
-        if (container.current) {
-            const subscription = subscribe({
-                target: container.current,
-                actions: [
-                    {
-                        key: t('json_viewer.copy'),
-                        icon: faCopy,
-                        action: (clickedElement) => {
-                            let parent = clickedElement;
-                            while (parent && parent.tagName !== 'TR') {
-                                parent = parent.parentNode;
-                            }
-
-                            const copyValue = parent.dataset.copyValue
-                            toClipboard(copyValue)
+        if (!container.current) {
+            return () => { }
+        }
+
+        const subscription = subscribe({
+            target: container.current,
+            actions: [
+                {
+                    key: t('json_viewer.copy'),
+                    icon: faCopy,
+                    action: (clickedElement) => {
+                        let parent = clickedElement;
+                        while (parent && parent.tagName !== 'TR') {
+                            parent = parent.parentNode;
                         }
+
+                        const copyValue = parent.dataset.copyValue
+                        toClipboard(copyValue)
                     }
-                ]
-            })
+                }
+            ]
+        })
 
-            return () => {
-                subscription.unsubscribe();
-            }
+        return () => {
+            subscription.unsubscribe();
         }
     }
 
@@ -137,7 +139,7 @@ export const useJsonViewer = ({ json, search, container }: JsonViewerViewModelTy
     }, [searchTerm])
 
     useEffect(() => {
-        registerMenuOptions();
+        const unsubscribe = registerMenuOptions();
 
         if (search.current) {
             search.current.addEventListener('input', handleSearchInput)
@@ -147,6 +149,7 @@ export const useJsonViewer = ({ json, search, container }: JsonViewerViewModelTy
             if (search.current) {
                 search.current.removeEventListener('input', handleSearchInput)
             }
+            unsubscribe()
         }
     }, [])
 
diff --git a/react-ui/src/shared/provider/menu/menu.provider.tsx b/react-ui/src/shared/provider/menu/menu.provider.tsx
index b2525692b..f3af8e5c1 100644
--- a/react-ui/src/shared/provider/menu/menu.provider.tsx
+++ b/react-ui/src/shared/provider/menu/menu.provider.tsx
@@ -19,13 +19,11 @@ type Action = {
 }
 
 interface MenuProviderType {
-    subscribe: (value: SubscriptionValue) => MenuSubscription
+    subscribe: ((value: SubscriptionValue) => MenuSubscription) | null;
 }
 
 const MenuContext = createContext<MenuProviderType>({
-    subscribe: function (): MenuSubscription {
-        throw new Error("Function not implemented.");
-    }
+    subscribe: null
 })
 
 interface SubscriptionValue {
@@ -33,11 +31,16 @@ interface SubscriptionValue {
     actions: Array<Action>
 }
 
+interface SubscriptionMap {
+    [id: string]: SubscriptionValue
+}
+
 
 export const MenuProvider: React.FC<BasicProp> = ({ children }) => {
     const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 });
     const [showMenu, setShowMenu] = useState(false);
-    const [subscribedTargets, setSubscribedTargets] = useState<Array<SubscriptionValue>>([])
+    const [subscribedTargets, setSubscribedTargets] = useState<SubscriptionMap>({});
+
     const { logout } = useAuth()
 
     const { t } = useTranslation('common')
@@ -61,12 +64,15 @@ export const MenuProvider: React.FC<BasicProp> = ({ children }) => {
 
     const handleContextMenu = (event: React.MouseEvent<HTMLElement>) => {
         event.preventDefault();
-        const targets = subscribedTargets.filter(({ target }) => target.contains(event.target as HTMLElement))
+
+        const targets = Object.values(subscribedTargets).filter(
+            ({ target }) => target.contains(event.target as HTMLElement)
+        );
 
         setMenuPosition({ top: event.pageY, left: event.pageX });
-        setMenuItems(targets)
-        setClickedHtmlElement(event.target as HTMLElement)
-        displayMenu()
+        setMenuItems(targets);
+        setClickedHtmlElement(event.target as HTMLElement);
+        displayMenu();
     };
 
     const displayMenu = () => {
@@ -90,20 +96,27 @@ export const MenuProvider: React.FC<BasicProp> = ({ children }) => {
 
     const value = useMemo<MenuProviderType>(() => {
         return {
-            subscribe(target) {
-                const index = subscribedTargets.length;
+            subscribe(target: SubscriptionValue) {
+                const subscriptionId = crypto.randomUUID(); // Generate unique ID
 
-                setSubscribedTargets([...subscribedTargets, target])
+                setSubscribedTargets(prev => ({
+                    ...prev,
+                    [subscriptionId]: target
+                }));
 
                 const subscription: MenuSubscription = {
                     unsubscribe() {
-                        setSubscribedTargets([...subscribedTargets.splice(index, 1)])
+                        setSubscribedTargets(prev => {
+                            const next = { ...prev };
+                            delete next[subscriptionId];
+                            return next;
+                        });
                     },
                 }
-                return subscription
+                return subscription;
             },
         } as MenuProviderType
-    }, [])
+    }, []);
 
     return (
         <MenuContext.Provider value={value}>
diff --git a/react-ui/yarn.lock b/react-ui/yarn.lock
index 62e8d8fa1..ec57231a8 100755
--- a/react-ui/yarn.lock
+++ b/react-ui/yarn.lock
@@ -4073,6 +4073,11 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3, cross-spawn@^7.0.5:
     shebang-command "^2.0.0"
     which "^2.0.1"
 
+crypto-js@^4.2.0:
+  version "4.2.0"
+  resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631"
+  integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==
+
 crypto-random-string@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
-- 
GitLab


From ea16b7fdaeb102e5aafd3dd19f1c5b5b99d35695 Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@@stud.h-da.de>
Date: Thu, 9 Jan 2025 18:42:37 +0100
Subject: [PATCH 28/79] (ui): increase nginx buffer size

---
 react-ui/docker/webserver/nginx.conf | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/react-ui/docker/webserver/nginx.conf b/react-ui/docker/webserver/nginx.conf
index 4ddf7f20d..b9028bec3 100644
--- a/react-ui/docker/webserver/nginx.conf
+++ b/react-ui/docker/webserver/nginx.conf
@@ -25,9 +25,9 @@ http {
 
     # Buffer size settings
     client_body_buffer_size 10K;
-    client_header_buffer_size 1k;
+    client_header_buffer_size 8k;
     client_max_body_size 8m;
-    large_client_header_buffers 2 1k;
+    large_client_header_buffers 4 8k;
 
     # File descriptor cache
     open_file_cache max=2000 inactive=20s;
-- 
GitLab


From e214ef7403ff3a415c9f18a9ede2055296566a9e Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@@stud.h-da.de>
Date: Thu, 9 Jan 2025 18:48:33 +0100
Subject: [PATCH 29/79] (ui): refactor assets

---
 react-ui/assets/logo.svg                      |  17 -----------------
 react-ui/index.html                           |   5 +++--
 react-ui/public/favicon.ico                   | Bin 3870 -> 31533 bytes
 .../protected.layout/protected.layout.tsx     |   2 +-
 react-ui/tsconfig.json                        |   1 -
 react-ui/vite.config.mjs                      |   1 -
 6 files changed, 4 insertions(+), 22 deletions(-)
 delete mode 100755 react-ui/assets/logo.svg
 mode change 100755 => 100644 react-ui/public/favicon.ico

diff --git a/react-ui/assets/logo.svg b/react-ui/assets/logo.svg
deleted file mode 100755
index b7f71bd90..000000000
--- a/react-ui/assets/logo.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<!-- Created with Vectornator (http://vectornator.io/) -->
-<svg height="100%" stroke-miterlimit="10" style="fill-rule:nonzero;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;" version="1.1" viewBox="0 0 113.4 212.625" width="100%" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:vectornator="http://vectornator.io" xmlns:xlink="http://www.w3.org/1999/xlink">
-<defs>
-<radialGradient cx="170.235" cy="146.046" gradientTransform="matrix(1.00001 -8.65109e-05 8.65119e-05 1 -115.465 -116.986)" gradientUnits="userSpaceOnUse" id="RadialGradient" r="217.591">
-<stop offset="0" stop-color="#c456f7"/>
-<stop offset="1" stop-color="#34054a"/>
-</radialGradient>
-<filter color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse" height="209.692" id="Filter" width="111.957" x="0.722269" y="2.46642">
-<feDropShadow dx="-4.37114e-08" dy="1" flood-color="#050505" flood-opacity="1" in="SourceGraphic" result="Shadow" stdDeviation="1"/>
-</filter>
-</defs>
-<g id="Layer-1" vectornator:layerName="Layer 1">
-<path d="M35.1413 3.47016L35.1416 6.93891L27.1415 6.93961L27.1464 63.3771C21.6096 65.0011 16.4869 67.0445 12.2717 69.6596C-9.35807 83.0789 12.5182 123.232 12.5264 123.222C12.5341 123.213 12.5498 123.2 12.5576 123.191C13.1518 124.609 14.5144 125.761 16.5579 126.534C18.7737 127.372 21.8204 127.855 26.8082 128.408C25.0644 132.318 24.4639 137.732 25.3409 144.846C26.0816 150.854 28.2327 155.309 32.5924 161.533C32.9615 162.06 34.1761 163.796 34.3427 164.033C35.013 164.984 35.5416 165.705 35.9991 166.408C38.1084 169.647 39.1319 172.149 39.3124 174.814C39.3701 175.665 39.3355 180.513 39.251 187.751C39.2362 189.024 39.0999 200.614 39.0959 200.907C37.7122 201.653 36.7523 203.069 36.7525 204.751C36.7527 207.19 38.7205 209.157 41.1591 209.157C43.5978 209.157 45.5653 207.189 45.5651 204.751C45.5649 203.019 44.5477 201.568 43.096 200.844C43.1023 200.341 43.2363 189.045 43.2511 187.782C43.3388 180.268 43.3816 175.583 43.3124 174.563C43.0775 171.096 41.7912 168.012 39.3427 164.251C38.854 163.5 38.3197 162.708 37.6237 161.72C37.4507 161.474 36.2342 159.766 35.8735 159.251C31.8564 153.517 29.9529 149.563 29.3096 144.346C28.2621 135.848 29.4895 130.5 32.027 127.533C32.6413 126.815 33.2789 126.306 33.9019 125.97C34.2334 125.792 34.4442 125.7 34.4956 125.689C35.5735 125.448 36.2365 124.392 35.9954 123.314C35.7543 122.236 34.6982 121.542 33.6202 121.783C33.2264 121.871 32.6655 122.078 31.9953 122.439C31.0669 122.939 30.1635 123.734 29.3079 124.658C23.0392 124.019 20.0922 123.577 17.9951 122.784C16.1482 122.086 15.9773 121.63 16.7137 120.347C25.511 115.923 43.9287 113.157 55.0885 113.156C63.8081 113.155 79.7952 116.873 90.4333 119.622C93.9977 120.542 94.7294 120.755 96.621 121.277C94.2649 123.034 89.4439 124.738 83.3087 125.247C83.0835 125.266 82.9434 125.443 82.7462 125.529C82.6074 125.348 82.5171 125.106 82.3711 124.935C81.4271 123.831 80.3863 122.999 79.3396 122.435C78.6693 122.074 78.1085 121.867 77.7145 121.779C76.6365 121.538 75.5805 122.233 75.3396 123.31C75.0987 124.388 75.7619 125.444 76.8399 125.685C76.8913 125.697 77.1021 125.788 77.4337 125.967C78.0567 126.302 78.6942 126.81 79.3088 127.529C81.8468 130.496 83.0751 135.844 82.029 144.341C81.3867 149.559 79.4839 153.513 75.4678 159.248C75.1071 159.763 73.8909 161.471 73.7179 161.717C73.0221 162.705 72.488 163.498 71.9994 164.248C69.5516 168.009 68.2658 171.094 68.0315 174.561C67.9625 175.581 68.0061 180.266 68.0951 187.78C68.1102 189.055 68.2793 200.673 68.2838 200.967C66.9421 201.725 66.0027 203.098 66.0028 204.749C66.0031 207.187 67.9709 209.155 70.4095 209.155C72.8481 209.154 74.8156 207.187 74.8154 204.748C74.8153 202.975 73.7598 201.482 72.2526 200.779C72.2461 200.277 72.1101 189.009 72.0952 187.748C72.0095 180.511 71.974 175.662 72.0316 174.811C72.2116 172.146 73.2659 169.644 75.3746 166.404C75.8321 165.701 76.3292 164.981 76.9994 164.029C77.1659 163.793 78.3803 162.056 78.7492 161.529C83.1079 155.305 85.2582 150.849 85.9979 144.841C86.8306 138.077 86.2654 132.917 84.7153 129.06C93.073 128.178 99.944 125.471 101.777 121.527C105.258 116.592 120.674 81.4184 100.46 69.1833C96.4145 66.7344 91.6503 64.7196 86.3971 63.1845L86.3922 6.93448L78.3609 6.93517L78.3606 3.46642L35.1413 3.47016ZM31.1419 10.9393L39.1107 10.9386L39.3309 27.9386C39.3406 28.6841 39.9605 29.2606 40.7061 29.2509C41.4516 29.2413 42.0593 28.6214 42.0497 27.8758L41.7983 10.9383L44.517 10.9381L44.7998 27.9381C44.8108 28.6836 45.3981 29.2615 46.1436 29.2505C46.8892 29.2394 47.4983 28.6209 47.4873 27.8753L47.2358 10.9379L49.9546 10.9376L50.2061 27.9376C50.2169 28.6831 50.8357 29.2608 51.5812 29.25C52.3267 29.2392 52.9044 28.6203 52.8936 27.8749L52.6421 10.9374L55.3609 10.9372L55.6124 27.9371C55.623 28.6827 56.242 29.2601 56.9875 29.2495C57.733 29.2389 58.3418 28.6199 58.3312 27.8744L58.0797 10.9369L60.8297 10.9367L61.05 27.9367C61.0546 28.3094 61.2147 28.6381 61.4563 28.8741C61.6979 29.1102 62.0211 29.2537 62.3938 29.2491C63.1394 29.2398 63.7468 28.6194 63.7375 27.8739L63.5173 10.9365L66.2986 10.9362L66.4875 27.905C66.4957 28.6505 67.1171 29.2568 67.8627 29.2486C68.6082 29.2404 69.1834 28.6503 69.1751 27.9047L68.9861 10.936L71.7674 10.9357L71.9564 27.9357C71.9605 28.3085 72.1132 28.6372 72.3627 28.8732C72.6122 29.1091 72.9587 29.2523 73.3315 29.2481C74.077 29.2398 74.6833 28.6498 74.6751 27.9042L74.4862 10.9355L82.3925 10.9348L82.3969 62.2473C78.1953 61.2363 73.8195 60.4151 69.2716 59.936L69.0841 59.936L69.0846 65.9672L62.3352 73.3116L62.211 82.5928L62.212 94.7803L56.5244 94.7808L50.3056 94.7814L50.2733 82.9376L50.1163 73.3126L43.1468 65.8132L43.1463 60.0945L31.1463 62.3455L31.1419 10.9393ZM46.0197 41.188L45.9904 64.3755L52.9599 71.8749L53.1492 91.9374L59.368 91.9368L59.5225 71.8743L66.2407 64.5612L66.2387 41.3425L46.0197 41.188ZM45.5578 121.282C45.0484 121.232 44.5158 121.369 44.0891 121.719C43.2356 122.421 43.1382 123.71 43.8394 124.563C43.8712 124.602 43.9181 124.67 44.0269 124.813C44.2163 125.062 44.4521 125.354 44.6832 125.688C45.3494 126.65 45.998 127.755 46.621 128.938C48.9603 133.379 50.0248 137.836 49.1222 141.875C48.4351 144.95 46.6061 147.711 43.4353 150.126C43.1568 150.338 42.1644 150.942 40.7792 151.751C40.6905 151.803 37.4839 153.662 37.4356 153.689C36.4728 154.23 36.1131 155.445 36.6545 156.408C37.1959 157.37 38.4106 157.699 39.3734 157.157C39.4251 157.128 42.7199 155.272 42.8108 155.22C44.3781 154.304 45.4057 153.669 45.8731 153.313C49.7829 150.336 52.1324 146.76 53.0285 142.75C54.1746 137.622 52.9238 132.266 50.1834 127.063C49.4811 125.729 48.7181 124.526 47.9643 123.438C47.5056 122.775 47.1244 122.271 46.9017 122C46.5511 121.574 46.0673 121.332 45.5578 121.282ZM65.7769 121.28C65.2675 121.33 64.7837 121.572 64.4331 121.999C64.2105 122.27 63.8293 122.774 63.3708 123.436C62.6172 124.525 61.8858 125.728 61.1835 127.062C58.444 132.265 57.163 137.621 58.3099 142.749C59.2067 146.759 61.5569 150.335 65.4671 153.311C65.9346 153.667 66.9935 154.302 68.5611 155.217C68.6519 155.27 71.9158 157.125 71.9675 157.154C72.9304 157.696 74.145 157.367 74.6862 156.404C75.2275 155.441 74.8676 154.227 73.9048 153.686C73.8565 153.658 70.6495 151.8 70.5608 151.748C69.1754 150.939 68.1829 150.336 67.9044 150.124C64.7332 147.71 62.9036 144.948 62.2161 141.874C61.3128 137.835 62.3766 133.378 64.715 128.936C65.3378 127.753 65.9862 126.649 66.6522 125.686C66.8833 125.352 67.1191 125.06 67.3084 124.811C67.4172 124.668 67.4953 124.6 67.5272 124.561C68.2282 123.708 68.0992 122.418 67.2457 121.717C66.8189 121.367 66.2862 121.23 65.7769 121.28ZM28.3735 160.064C27.8641 160.114 27.3492 160.357 26.9985 160.783C24.0604 164.358 22.5881 168.723 22.5621 174.253C22.5614 174.404 22.6311 200.839 22.627 200.877C21.1966 201.608 20.1896 203.036 20.1898 204.753C20.19 207.191 22.1578 209.159 24.5964 209.159C27.0351 209.158 29.0026 207.191 29.0024 204.752C29.0022 203.061 28.0235 201.65 26.627 200.908C26.6562 200.425 26.6538 197.055 26.6259 187.658C26.6229 186.662 26.5615 174.385 26.5622 174.252C26.584 169.618 27.7563 166.157 30.0925 163.314C30.7939 162.461 30.6644 161.203 29.811 160.502C29.3844 160.151 28.8829 160.015 28.3735 160.064ZM82.9679 160.06C82.4585 160.01 81.9571 160.147 81.5304 160.497C80.6772 161.199 80.5479 162.457 81.2494 163.31C83.5862 166.152 84.7591 169.613 84.7817 174.247C84.7823 174.378 84.7241 199.67 84.7527 200.841C83.3011 201.564 82.2529 203.015 82.253 204.747C82.2533 207.186 84.2524 209.153 86.691 209.153C89.1295 209.153 91.0971 207.185 91.0969 204.747C91.0967 203.049 90.1265 201.611 88.7215 200.872C88.7173 200.833 88.7318 194.753 88.7516 187.684C88.7544 186.688 88.7824 174.398 88.7817 174.247C88.7548 168.717 87.2817 164.353 84.343 160.778C83.9922 160.352 83.4774 160.109 82.9679 160.06Z" fill="url(#RadialGradient)" fill-rule="nonzero" filter="url(#Filter)" stroke="none" vectornator:shadowAngle="1.5708" vectornator:shadowColor="#050505" vectornator:shadowOffset="1" vectornator:shadowOpacity="1" vectornator:shadowRadius="2"/>
-</g>
-</svg>
diff --git a/react-ui/index.html b/react-ui/index.html
index 91d50a11c..3dc374a59 100755
--- a/react-ui/index.html
+++ b/react-ui/index.html
@@ -5,13 +5,14 @@
     <link rel="icon" href="favicon.ico" />
     <meta name="viewport" content="width=device-width, initial-scale=1" />
     <meta name="theme-color" content="#000000" />
+    <meta name="author" content="Matthias Feyll" />
     <meta
       name="description"
-      content="Web site created using create-react-app"
+      content="goSDN web ui"
     />
     <link rel="apple-touch-icon" href="logo.png" />
     <link rel="manifest" href="manifest.json" />
-    <title>goSDN</title>
+    <title>goSDN - ui</title>
   </head>
   <body>
     <noscript>You need to enable JavaScript to run this app.</noscript>
diff --git a/react-ui/public/favicon.ico b/react-ui/public/favicon.ico
old mode 100755
new mode 100644
index a11777cc471a4344702741ab1c8a588998b1311a..ae6dcf05241b89f446e88d15b81ffd69202fa83a
GIT binary patch
literal 31533
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
UF6((4fUd^&boFyt=akR{0H5d7UH||9

literal 3870
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
ZtMWJ#1p_C<F-T5Hu2|;y@Dg%;1puB)gNgtE

diff --git a/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx b/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx
index b017cf56f..0f0e8161e 100755
--- a/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx
+++ b/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx
@@ -1,4 +1,3 @@
-import logo from '@assets/logo.svg';
 import { faCircleUser, faRightFromBracket } from "@fortawesome/free-solid-svg-icons";
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { useAppDispatch, useAppSelector } from '@hooks';
@@ -11,6 +10,7 @@ import { Dropdown } from "react-bootstrap";
 import { useTranslation } from "react-i18next";
 import { Link, Outlet, useNavigate } from "react-router-dom";
 import "./protected.layout.scss";
+import logo from '/public/logo.png';
 
 
 export const ProtectedLayout = () => {
diff --git a/react-ui/tsconfig.json b/react-ui/tsconfig.json
index c679b7100..d40af31cc 100755
--- a/react-ui/tsconfig.json
+++ b/react-ui/tsconfig.json
@@ -22,7 +22,6 @@
 
         "baseUrl": ".",
         "paths": {
-            "@assets/*": ["assets/*"],
             "@api/*": ["src/shared/api/*"],
             "@reducer/*": ["src/stores/reducer/*"],
             "@provider/*": ["src/shared/provider/*"],
diff --git a/react-ui/vite.config.mjs b/react-ui/vite.config.mjs
index 83378d6ee..1304138c1 100755
--- a/react-ui/vite.config.mjs
+++ b/react-ui/vite.config.mjs
@@ -58,7 +58,6 @@ export default defineConfig({
     },
     resolve: {
         alias: {
-            '@assets': '/assets',
             '@api': '/src/shared/api',
             '@reducer': '/src/stores/reducer',
             '@provider': '/src/shared/provider',
-- 
GitLab


From d54ff5ba2be4ce59f390a4e0ca1421d658f430b1 Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@@stud.h-da.de>
Date: Thu, 9 Jan 2025 19:07:17 +0100
Subject: [PATCH 30/79] (ui): minor css improvements

---
 react-ui/src/components/devices/view/device.scss     |  1 +
 .../components/devices/view/device.view.table.tsx    |  2 --
 .../src/components/devices/view/device.view.tabs.tsx |  2 --
 react-ui/src/components/devices/view/device.view.tsx | 12 ++++++------
 react-ui/vite.config.mjs                             |  1 -
 5 files changed, 7 insertions(+), 11 deletions(-)

diff --git a/react-ui/src/components/devices/view/device.scss b/react-ui/src/components/devices/view/device.scss
index 540cd4d01..866ce81eb 100755
--- a/react-ui/src/components/devices/view/device.scss
+++ b/react-ui/src/components/devices/view/device.scss
@@ -57,5 +57,6 @@
     &.active {
         color: map-get($theme-colors, primary);
         font-weight: 500;
+        text-decoration: underline;
     }
 }
diff --git a/react-ui/src/components/devices/view/device.view.table.tsx b/react-ui/src/components/devices/view/device.view.table.tsx
index 56ad05f3f..8800010e2 100755
--- a/react-ui/src/components/devices/view/device.view.table.tsx
+++ b/react-ui/src/components/devices/view/device.view.table.tsx
@@ -48,7 +48,6 @@ export const DeviceViewTable = (searchRef: MutableRefObject<HTMLInputElement>) =
                         <td data-copy-value={deviceId} dangerouslySetInnerHTML={{ __html: search ? insertMarkTags(cropedId, search) : DOMPurify.sanitize(cropedId) }}></td>
                     </OverlayTrigger>
                     <td data-copy-value={username} dangerouslySetInnerHTML={{ __html: search ? insertMarkTags(username, search) : DOMPurify.sanitize(username) }}></td>
-                    <td></td>
                 </tr>
             )
         })
@@ -61,7 +60,6 @@ export const DeviceViewTable = (searchRef: MutableRefObject<HTMLInputElement>) =
                     <th>{t('device.table.header.name')}</th>
                     <th>{t('device.table.header.uuid')}</th>
                     <th>{t('device.table.header.user')}</th>
-                    <th>{t('device.table.header.last_updated')}</th>
                 </tr>
             </thead>
             <tbody>
diff --git a/react-ui/src/components/devices/view/device.view.tabs.tsx b/react-ui/src/components/devices/view/device.view.tabs.tsx
index a2768a0ea..ef8ba120f 100755
--- a/react-ui/src/components/devices/view/device.view.tabs.tsx
+++ b/react-ui/src/components/devices/view/device.view.tabs.tsx
@@ -24,8 +24,6 @@ export const DeviceViewTabs = (activeTab: DeviceViewTabValues) => {
             <>
                 {jsonYang &&
                     <JsonViewer json={jsonYang} />
-
-                    //<ReactJson src={selectedDevice.json} name={false} collapsed={true} quotesOnKeys={false} />
                 }
             </>
         );
diff --git a/react-ui/src/components/devices/view/device.view.tsx b/react-ui/src/components/devices/view/device.view.tsx
index a2c8458a7..518c12af4 100755
--- a/react-ui/src/components/devices/view/device.view.tsx
+++ b/react-ui/src/components/devices/view/device.view.tsx
@@ -15,19 +15,19 @@ const DeviceView = () => {
         <div className='m-4 pt-4'>
             <Container fluid>
                 <Row>
-                    <Col sm={5}>
+                    <Col lg={5} sm={12}>
                         <Container className='bg-white rounded c-box'>
                             <Row>
                                 <Col sm={12} className='mt-4'><h3 className='text-black-50'>{t('device.title')}</h3></Col>
                             </Row>
 
                             <Row className='align-items-center'>
-                                <Col sm={6}>
+                                <Col xs={12} sm={6}>
                                     <Form.Group controlId='device.search' className='p-0 mx-1 pt-2'>
                                         <Form.Control type="text" placeholder={t('device.search.placeholder')} ref={searchRef} />
                                     </Form.Group>
                                 </Col>
-                                <Col sm={{ span: 3, offset: 3 }} className='pt-2'>
+                                <Col xs={12} sm={6} className='pt-2'>
                                     <Button variant='primary' className='w-100 my-auto'>{t('device.add_device_button')}</Button>
                                 </Col>
                             </Row>
@@ -39,10 +39,10 @@ const DeviceView = () => {
                             </Row>
                         </Container>
                     </Col>
-                    <Col sm={7}>
+                    <Col xs={12} lg={7} className='mt-5 mt-lg-0'>
                         <Container className='bg-white rounded c-box'>
                             <Row>
-                                <Col sm={12} className='mt-4'>
+                                <Col xs={12} className='mt-4'>
                                     <Nav className='justify-content-around'>
                                         <NavLink className={handleActiveTabLink(DeviceViewTabValues.METADATA) + " tab-links"} onClick={() => setActiveTab(DeviceViewTabValues.METADATA)}>{t('device.tabs.metadata.title')}</NavLink>
                                         <NavLink className={handleActiveTabLink(DeviceViewTabValues.YANGMODEL) + " tab-links"} onClick={() => setActiveTab(DeviceViewTabValues.YANGMODEL)}>{t('device.tabs.yang_model.title')}</NavLink>
@@ -51,7 +51,7 @@ const DeviceView = () => {
                             </Row>
 
                             <Row className='align-items-start'>
-                                <Col sm={12} className='pt-2'>
+                                <Col xs={12}>
                                     {DeviceViewTabs(activeTab)}
                                 </Col>
                             </Row>
diff --git a/react-ui/vite.config.mjs b/react-ui/vite.config.mjs
index 1304138c1..33fd69cc7 100755
--- a/react-ui/vite.config.mjs
+++ b/react-ui/vite.config.mjs
@@ -1,7 +1,6 @@
 import react from '@vitejs/plugin-react';
 import { defineConfig } from 'vite';
 
-
 export default defineConfig({
     plugins: [react()],
     build: {
-- 
GitLab


From 4dae015f461a2858fa4e1cfa91926bc7f21b72bb Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@stud.h-da.de>
Date: Thu, 9 Jan 2025 19:10:49 +0100
Subject: [PATCH 31/79] (ui): fix import path

---
 react-ui/src/components/login/view/login.view.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/react-ui/src/components/login/view/login.view.tsx b/react-ui/src/components/login/view/login.view.tsx
index 38afc83a1..62c84eeb8 100755
--- a/react-ui/src/components/login/view/login.view.tsx
+++ b/react-ui/src/components/login/view/login.view.tsx
@@ -1,10 +1,10 @@
-import logo from '@assets/logo.svg'
 import { BasicProp } from '@shared/types/interfaces.type'
 import React, { useRef } from 'react'
 import { Alert, Button, Col, Container, Form, Image, Row, Spinner } from 'react-bootstrap'
 import { useTranslation } from 'react-i18next'
 import useLoginViewModel from '../viewmodel/login.viewmodel'
 import './login.scss'
+import logo from '/public/logo.svg'
 
 const LoginView: React.FC<BasicProp> = () => {
     const { t } = useTranslation('common')
-- 
GitLab


From 227b80e7932d21b89ab80164af35a20f9c3721c6 Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@stud.h-da.de>
Date: Fri, 10 Jan 2025 01:42:44 +0100
Subject: [PATCH 32/79] (ui): remove sidebar

---
 .../components/devices/view/device.view.tsx   |   4 +-
 react-ui/src/routes.tsx                       |  25 ++--
 .../protected.layout/protected.layout.scss    |  49 ++++++--
 .../protected.layout/protected.layout.tsx     |  20 +--
 react-ui/src/shared/style/box.scss            |  28 +++--
 react-ui/src/shared/style/colors.scss         |  18 +--
 react-ui/src/shared/style/utils.scss          |   4 -
 .../src/shared/utils/loading-fallback.tsx     | 117 ++++++++++++++++++
 8 files changed, 207 insertions(+), 58 deletions(-)
 create mode 100644 react-ui/src/shared/utils/loading-fallback.tsx

diff --git a/react-ui/src/components/devices/view/device.view.tsx b/react-ui/src/components/devices/view/device.view.tsx
index 518c12af4..4ef007327 100755
--- a/react-ui/src/components/devices/view/device.view.tsx
+++ b/react-ui/src/components/devices/view/device.view.tsx
@@ -16,7 +16,7 @@ const DeviceView = () => {
             <Container fluid>
                 <Row>
                     <Col lg={5} sm={12}>
-                        <Container className='bg-white rounded c-box'>
+                        <Container className='bg-white c-box'>
                             <Row>
                                 <Col sm={12} className='mt-4'><h3 className='text-black-50'>{t('device.title')}</h3></Col>
                             </Row>
@@ -40,7 +40,7 @@ const DeviceView = () => {
                         </Container>
                     </Col>
                     <Col xs={12} lg={7} className='mt-5 mt-lg-0'>
-                        <Container className='bg-white rounded c-box'>
+                        <Container className='bg-white c-box'>
                             <Row>
                                 <Col xs={12} className='mt-4'>
                                     <Nav className='justify-content-around'>
diff --git a/react-ui/src/routes.tsx b/react-ui/src/routes.tsx
index 532d03fbf..a476feaae 100755
--- a/react-ui/src/routes.tsx
+++ b/react-ui/src/routes.tsx
@@ -1,5 +1,6 @@
 import { BasicLayout } from "@layout/basic.layout";
 import { ProtectedLayout } from "@layout/protected.layout/protected.layout";
+import DelayedRender, { SplashScreen } from "@utils/loading-fallback";
 import { lazy, Suspense } from 'react';
 import { createBrowserRouter, createRoutesFromElements, Navigate, Route } from "react-router-dom";
 
@@ -10,17 +11,16 @@ export const LOGIN_URL = '/login';
 const DeviceView = lazy(() => import('./components/devices/view/device.view'));
 const LoginLayout = lazy(() => import('./components/login/layouts/login.layout'));
 
-// Loading fallback component
-const LoadingFallback = () => <div>Loading...</div>;
-
 export const router = createBrowserRouter(
     createRoutesFromElements(
         <Route element={<BasicLayout />}>
             <Route
                 path={LOGIN_URL}
                 element={
-                    <Suspense fallback={<LoadingFallback />}>
-                        <LoginLayout />
+                    <Suspense fallback={null}>
+                        <DelayedRender>
+                            <LoginLayout />
+                        </DelayedRender>
                     </Suspense>
                 }
             />
@@ -28,9 +28,16 @@ export const router = createBrowserRouter(
                 <Route
                     path={DEVICE_URL}
                     element={
-                        <Suspense fallback={<LoadingFallback />}>
-                            <DeviceView />
-                        </Suspense>
+                        <DelayedRender
+                            loading={{
+                                minimumLoadingTime: 1000,
+                                component: SplashScreen
+                            }}
+                        >
+                            <Suspense fallback={null}>
+                                <DeviceView />
+                            </Suspense>
+                        </DelayedRender>
                     }
                 />
                 <Route
@@ -38,6 +45,6 @@ export const router = createBrowserRouter(
                     element={<Navigate to={DEVICE_URL} replace={true} />}
                 />
             </Route>
-        </Route>
+        </Route >
     )
 );
\ No newline at end of file
diff --git a/react-ui/src/shared/layouts/protected.layout/protected.layout.scss b/react-ui/src/shared/layouts/protected.layout/protected.layout.scss
index 07b38d5a7..713e63481 100755
--- a/react-ui/src/shared/layouts/protected.layout/protected.layout.scss
+++ b/react-ui/src/shared/layouts/protected.layout/protected.layout.scss
@@ -1,7 +1,5 @@
 @import "/src/shared/style/colors.scss";
 
-$sidebar-width: 4.5em;
-
 .head-links {
     text-decoration: none;
     color: map-get($theme-colors, dark);
@@ -19,11 +17,46 @@ $sidebar-width: 4.5em;
     }
 }
 
-.sidebar {
-    width: $sidebar-width;
-    height: 100vh;
-}
+// Add these styles to your protected.layout.scss
+nav {
+    border-radius: 0 0 $border-radius $border-radius;
+    box-shadow:
+        0px 4px 8px mix(map-get($theme-colors, "primary"), map-get($theme-colors, "dark"), 35%),
+        0px 2px 4px mix(map-get($theme-colors, "primary"), map-get($theme-colors, "dark"), 20%);
+
+    .head-links {
+        text-decoration: none;
+        color: map-get($theme-colors, "dark");
+        padding: 8px 16px;
+        margin: 0 4px;
+        border-radius: 12px;
+        transition: all 0.2s ease;
 
-.main-content {
-    margin-left: $sidebar-width;
+        &:hover {
+            background-color: map-get($theme-colors, "bg-primary");
+        }
+
+        &.active {
+            color: map-get($theme-colors, "primary");
+            background-color: map-get($theme-colors, "primary::hover");
+        }
+    }
+
+    .dropdown-menu {
+        border-radius: $border-radius;
+        box-shadow:
+            0px 4px 8px mix(map-get($theme-colors, "primary"), map-get($theme-colors, "dark"), 35%),
+            0px 2px 4px mix(map-get($theme-colors, "primary"), map-get($theme-colors, "dark"), 20%);
+        border: none;
+        padding: 8px;
+
+        .dropdown-item {
+            border-radius: 8px;
+            padding: 8px 16px;
+
+            &:hover {
+                background-color: map-get($theme-colors, "bg-primary");
+            }
+        }
+    }
 }
diff --git a/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx b/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx
index 0f0e8161e..b1d70b823 100755
--- a/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx
+++ b/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx
@@ -69,14 +69,6 @@ export const ProtectedLayout = () => {
     }
   );
 
-  const VerticalSidebar = () => {
-    return (
-      <div className="d-flex fixed-top flex-column flex-shrink-0 bg-white sidebar justify-content-end border-end border-dark py-3 z-2">
-        <FontAwesomeIcon className="clickable icon" icon={faRightFromBracket} onClick={logout} size="2x" />
-      </div>
-    )
-  }
-
   const HorizontalNavbar = () => {
     return (
       <nav className="bg-white border-bottom border-dark py-2 d-flex align-items-center z-3 position-relative">
@@ -87,15 +79,18 @@ export const ProtectedLayout = () => {
 
         <Dropdown className="ms-auto px-3">
           <Dropdown.Toggle as={UserIconToggle}>
-            <FontAwesomeIcon icon={faCircleUser} className="icon clickable" />
+            <FontAwesomeIcon icon={faCircleUser} className="clickable" size="2x" />
           </Dropdown.Toggle>
 
           <Dropdown.Menu as={UserIconMenu}>
             <Dropdown.Item eventKey="1">{user?.name}</Dropdown.Item>
             <hr />
-            <Dropdown.Item eventKey="1">
+            <Dropdown.Item eventKey="2">
               <Link className="text-decoration-none text-reset" to="/">{t('protected.link.settings')}</Link>
             </Dropdown.Item>
+            <Dropdown.Item eventKey="3" onClick={logout}>
+              <Link className="text-decoration-none text-reset" to="/"><FontAwesomeIcon className="clickable" icon={faRightFromBracket} />{t('protected.link.settings')}</Link>
+            </Dropdown.Item>
           </Dropdown.Menu>
         </Dropdown>
       </nav>
@@ -106,10 +101,7 @@ export const ProtectedLayout = () => {
     <div>
       <MenuProvider>
         {HorizontalNavbar()}
-        {VerticalSidebar()}
-        <div className='main-content'>
-          <Outlet />
-        </div>
+        <Outlet />
       </MenuProvider>
     </div>
   )
diff --git a/react-ui/src/shared/style/box.scss b/react-ui/src/shared/style/box.scss
index bd75fb00a..934861a2b 100755
--- a/react-ui/src/shared/style/box.scss
+++ b/react-ui/src/shared/style/box.scss
@@ -1,26 +1,30 @@
-@import './colors.scss';
+@import "./colors.scss";
 
 $box-padding: 10px;
 $border-radius: 20px;
- 
+$border-width: 2px;
 
 .c-box {
     padding: $box-padding;
     background-color: white;
-    box-shadow: 0px 4px 4px rgba(0,0,0, .35);
+    position: relative;
     border-radius: $border-radius;
+
+    background:
+        linear-gradient(white, white) padding-box,
+        linear-gradient(
+                180deg,
+                rgba(map-get($theme-colors, "primary"), 0.3) 0%,
+                rgba(map-get($theme-colors, "primary"), 0.1) 100%
+            )
+            border-box;
+    border: $border-width solid transparent;
+
+    box-shadow: 0px 1px 2px rgba(map-get($theme-colors, "dark"), 0.12);
 }
 
 .abstract-box {
     padding: 16px $box-padding;
-    font-size: .90em;
+    font-size: 0.9em;
     border-radius: calc($border-radius / 2);
 }
-
-
-// @each $color, $value in $theme-colors {
-//     .#{$color}-box {
-//         @extend .abstract-box;
-//         background-color: $value !important;
-//     }
-// }
diff --git a/react-ui/src/shared/style/colors.scss b/react-ui/src/shared/style/colors.scss
index 749af9e8e..d91ffb44e 100755
--- a/react-ui/src/shared/style/colors.scss
+++ b/react-ui/src/shared/style/colors.scss
@@ -1,11 +1,11 @@
 $theme-colors: (
-  'primary': #b350e0,
-  'primary::hover': #ddaff3af,
-  'bg-primary': #E1E1E1,
-  'danger': #ffdcdc,
-  'warning': #dbd116,
-  'dark': #595959,
-  'black': #000000,
+  "primary": #b350e0,
+  "primary::hover": #ddaff3af,
+  "bg-primary": #ededed,
+  "danger": #ffdcdc,
+  "warning": #dbd116,
+  "dark": #595959,
+  "black": #000000
 );
-  
-@import '/node_modules/bootstrap/scss/bootstrap';
+
+@import "/node_modules/bootstrap/scss/bootstrap";
diff --git a/react-ui/src/shared/style/utils.scss b/react-ui/src/shared/style/utils.scss
index d8be654f7..d6f34d301 100755
--- a/react-ui/src/shared/style/utils.scss
+++ b/react-ui/src/shared/style/utils.scss
@@ -7,7 +7,3 @@
         cursor: pointer;
     }
 }
-
-.icon {
-    font-size: 1.75em;
-}
diff --git a/react-ui/src/shared/utils/loading-fallback.tsx b/react-ui/src/shared/utils/loading-fallback.tsx
new file mode 100644
index 000000000..d1c6daa4a
--- /dev/null
+++ b/react-ui/src/shared/utils/loading-fallback.tsx
@@ -0,0 +1,117 @@
+import React, { useEffect, useState } from 'react';
+import { Col, Container, Row } from 'react-bootstrap';
+import logo from '/public/logo.png';
+
+interface DelayedRenderProps {
+    children: React.ReactNode;
+    loading?: {
+        minimumLoadingTime: number;
+        component: () => JSX.Element
+    }
+}
+
+export const SplashScreen = () => {
+    const [dots, setDots] = useState('');
+
+    useEffect(() => {
+        const dotsInterval = setInterval(() => {
+            setDots(prev => prev.length >= 3 ? '' : prev + '.');
+        }, 500);
+
+        return () => clearInterval(dotsInterval);
+    }, []);
+
+    return (
+        <div className="splash-screen-overlay">
+            <Container fluid className="h-100 d-flex align-items-center justify-content-center bg-bg-primary">
+                <Row>
+                    <Col className="text-center">
+                        <div className="loading-bounce mb-4">
+                            <img
+                                src={logo}
+                                alt="Logo"
+                                className="img-fluid"
+                                style={{ width: '120px', height: '120px', objectFit: 'contain' }}
+                            />
+                        </div>
+                        <div className="loading-text">
+                            <span className="h4 text-secondary">Loading</span>
+                            <span className="h4 text-secondary dots-width">{dots}</span>
+                        </div>
+                    </Col>
+                </Row>
+            </Container>
+
+            <style>
+                {`
+                    .splash-screen-overlay {
+                        position: fixed;
+                        top: 0;
+                        left: 0;
+                        width: 100%;
+                        height: 100%;
+                        background-color: #f8f9fa;
+                        z-index: 0;
+                        display: flex;
+                        align-items: center;
+                        justify-content: center;
+                    }
+
+                    .loading-bounce {
+                        animation: bounce 1s infinite;
+                    }
+
+                    @keyframes bounce {
+                        0%, 100% {
+                            transform: translateY(0);
+                        }
+                        50% {
+                            transform: translateY(-20px);
+                        }
+                    }
+
+                    .loading-text {
+                        display: flex;
+                        justify-content: center;
+                        align-items: center;
+                    }
+
+                    .dots-width {
+                        min-width: 24px;
+                        text-align: left;
+                        margin-left: 2px;
+                    }
+                `}
+            </style>
+        </div>
+    );
+};
+
+export const DelayedRender: React.FC<DelayedRenderProps> = ({
+    children,
+    loading
+}) => {
+    const [shouldRender, setShouldRender] = useState(false);
+
+    useEffect(() => {
+        if (!loading) {
+            setShouldRender(true);
+            return;
+        }
+
+        const timer = setTimeout(() => {
+            setShouldRender(true);
+        }, loading.minimumLoadingTime);
+
+        return () => clearTimeout(timer);
+    }, [loading]);
+
+    if (!shouldRender && loading) {
+        const LoadingComponent = loading.component;
+        return <LoadingComponent />;
+    }
+
+    return <>{children}</>;
+};
+
+export default DelayedRender;
\ No newline at end of file
-- 
GitLab


From 6d1785b9dec02bbfa58c65280aa4118527585b22 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Fri, 10 Jan 2025 08:29:27 +0000
Subject: [PATCH 33/79] [renovate] Update github.com/aristanetworks/goarista
 digest to 1f88a86

See merge request danet/gosdn!1151

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 10 +++++-----
 go.sum | 10 ++++++++++
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/go.mod b/go.mod
index 7c8225cdc..16daa3076 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module code.fbi.h-da.de/danet/gosdn
 go 1.23
 
 require (
-	github.com/aristanetworks/goarista v0.0.0-20250108214730-362a04c9d029
+	github.com/aristanetworks/goarista v0.0.0-20250108234106-1f88a86e2265
 	github.com/c-bata/go-prompt v0.2.6
 	github.com/docker/docker v24.0.9+incompatible
 	github.com/google/go-cmp v0.6.0
@@ -47,7 +47,7 @@ require (
 	github.com/gookit/color v1.5.4 // indirect
 	github.com/hashicorp/hcl v1.0.0 // indirect
 	github.com/inconshreveable/mousetrap v1.1.0 // indirect
-	github.com/klauspost/compress v1.17.9 // indirect
+	github.com/klauspost/compress v1.17.11 // indirect
 	github.com/kylelemons/godebug v1.1.0 // indirect
 	github.com/magiconair/properties v1.8.7 // indirect
 	github.com/mattn/go-colorable v0.1.13 // indirect
@@ -64,7 +64,7 @@ require (
 	github.com/pkg/term v1.2.0-beta.2 // indirect
 	github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
 	github.com/prometheus/client_model v0.6.1 // indirect
-	github.com/prometheus/common v0.57.0 // indirect
+	github.com/prometheus/common v0.61.0 // indirect
 	github.com/prometheus/procfs v0.15.1 // indirect
 	github.com/rabbitmq/amqp091-go v1.10.0
 	github.com/rivo/uniseg v0.4.4 // indirect
@@ -78,7 +78,7 @@ require (
 	github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
 	github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
 	golang.org/x/crypto v0.32.0
-	golang.org/x/net v0.33.0
+	golang.org/x/net v0.34.0
 	golang.org/x/sys v0.29.0 // indirect
 	golang.org/x/term v0.28.0 // indirect
 	golang.org/x/text v0.21.0 // indirect
@@ -123,6 +123,6 @@ require (
 	go.uber.org/atomic v1.9.0 // indirect
 	go.uber.org/multierr v1.9.0 // indirect
 	golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
-	google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20250106144421-5f5ef82da422 // indirect
 	gotest.tools/v3 v3.5.1 // indirect
 )
diff --git a/go.sum b/go.sum
index eb454ef9b..d1247f175 100644
--- a/go.sum
+++ b/go.sum
@@ -62,6 +62,8 @@ github.com/aristanetworks/goarista v0.0.0-20241115153057-bd75d7f26a44 h1:vb3HPPa
 github.com/aristanetworks/goarista v0.0.0-20241115153057-bd75d7f26a44/go.mod h1:C+YeQrhbMvCPh5wG6iqGiCD/zcITTpt4YQ1v4K0g5Vc=
 github.com/aristanetworks/goarista v0.0.0-20250108214730-362a04c9d029 h1:bvw2TILeXtuYfZ9rip/4DY933UuIvCwtvJmwvz978ac=
 github.com/aristanetworks/goarista v0.0.0-20250108214730-362a04c9d029/go.mod h1:C+YeQrhbMvCPh5wG6iqGiCD/zcITTpt4YQ1v4K0g5Vc=
+github.com/aristanetworks/goarista v0.0.0-20250108234106-1f88a86e2265 h1:NPQhasGGtAIxtDG4KQTcQviV9T6a98kbKSO0VKFRS+E=
+github.com/aristanetworks/goarista v0.0.0-20250108234106-1f88a86e2265/go.mod h1:1xldiSdHhqa1XIr6EPNnSBfwZEAMZwwJIiEtMS8yzkU=
 github.com/aristanetworks/gomap v0.0.0-20240724180630-b4cffb90720f h1:3GwV1IeLp0PwWcnbc9ZihE3osvexJf3PMjWSCGjtIqc=
 github.com/aristanetworks/gomap v0.0.0-20240724180630-b4cffb90720f/go.mod h1:bNzH6HFWav8D/ws3QlkjLpf9ZOdsUTDx+qJikWCcGRc=
 github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk=
@@ -198,6 +200,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
 github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
+github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
+github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
 github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
 github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
 github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
@@ -306,6 +310,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p
 github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
 github.com/prometheus/common v0.57.0 h1:Ro/rKjwdq9mZn1K5QPctzh+MA4Lp0BuYk5ZZEVhoNcY=
 github.com/prometheus/common v0.57.0/go.mod h1:7uRPFSUTbfZWsJ7MHY56sqt7hLQu3bxXHDnNhl8E9qI=
+github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ=
+github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s=
 github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
 github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
 github.com/protocolbuffers/txtpbfmt v0.0.0-20220608084003-fc78c767cd6a/go.mod h1:KjY0wibdYKc4DYkerHSbguaf3JeIPGhNJBp2BNiFH78=
@@ -464,6 +470,8 @@ golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
 golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
 golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
 golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
+golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
+golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -625,6 +633,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1:
 google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d h1:xJJRGY7TJcvIlpSrN3K6LAWgNFUILlO+OMAqtg9aqnw=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250106144421-5f5ef82da422 h1:3UsHvIr4Wc2aW4brOaSCmcxh9ksica6fHEr8P1XhkYw=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250106144421-5f5ef82da422/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
-- 
GitLab


From 3182bc05a4131fe9248a6074517159caa9c3a2af Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@stud.h-da.de>
Date: Fri, 10 Jan 2025 10:38:32 +0100
Subject: [PATCH 34/79] (ui): refactor navbar styles

---
 .../login/viewmodel/login.viewmodel.ts        |  6 +--
 .../protected.layout/protected.layout.scss    | 15 +++---
 .../protected.layout/protected.layout.tsx     | 50 +++++++++++--------
 react-ui/src/shared/style/box.scss            |  4 +-
 react-ui/src/shared/style/colors.scss         |  2 +
 5 files changed, 42 insertions(+), 35 deletions(-)

diff --git a/react-ui/src/components/login/viewmodel/login.viewmodel.ts b/react-ui/src/components/login/viewmodel/login.viewmodel.ts
index 60c39b55a..fabb0a861 100755
--- a/react-ui/src/components/login/viewmodel/login.viewmodel.ts
+++ b/react-ui/src/components/login/viewmodel/login.viewmodel.ts
@@ -7,9 +7,9 @@ export interface PageLoginState {
 }
 
 export default function useLoginViewModel() {
-    const {login, loginProperties} = useAuth();
-    const {isLoading: loginLoading, error: loginError, reset: resetLogin} = loginProperties!;
-    
+    const { login, loginProperties } = useAuth();
+    const { isLoading: loginLoading, error: loginError, reset: resetLogin } = loginProperties;
+
     const [localFormState, updateLocalFormState] = useState({
         submitted: false,
         valid: false,
diff --git a/react-ui/src/shared/layouts/protected.layout/protected.layout.scss b/react-ui/src/shared/layouts/protected.layout/protected.layout.scss
index 713e63481..52429031b 100755
--- a/react-ui/src/shared/layouts/protected.layout/protected.layout.scss
+++ b/react-ui/src/shared/layouts/protected.layout/protected.layout.scss
@@ -8,7 +8,6 @@
 
     &:hover {
         color: map-get($theme-colors, primary);
-        font-weight: 600;
     }
 
     &.active {
@@ -17,12 +16,14 @@
     }
 }
 
+#navbar {
+    padding: 1em !important;
+}
+
 // Add these styles to your protected.layout.scss
 nav {
-    border-radius: 0 0 $border-radius $border-radius;
-    box-shadow:
-        0px 4px 8px mix(map-get($theme-colors, "primary"), map-get($theme-colors, "dark"), 35%),
-        0px 2px 4px mix(map-get($theme-colors, "primary"), map-get($theme-colors, "dark"), 20%);
+    border-radius: $border-radius $border-radius;
+    padding: 0 !important;
 
     .head-links {
         text-decoration: none;
@@ -44,9 +45,7 @@ nav {
 
     .dropdown-menu {
         border-radius: $border-radius;
-        box-shadow:
-            0px 4px 8px mix(map-get($theme-colors, "primary"), map-get($theme-colors, "dark"), 35%),
-            0px 2px 4px mix(map-get($theme-colors, "primary"), map-get($theme-colors, "dark"), 20%);
+        box-shadow: $box-shadow;
         border: none;
         padding: 8px;
 
diff --git a/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx b/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx
index b1d70b823..5dc565455 100755
--- a/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx
+++ b/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx
@@ -6,7 +6,7 @@ import { MenuProvider } from '@provider/menu/menu.provider';
 import { DEVICE_URL, LOGIN_URL } from '@routes';
 import { fetchPnds, fetchUser } from '@shared/routine/user.routine';
 import React, { useEffect } from "react";
-import { Dropdown } from "react-bootstrap";
+import { Col, Container, Dropdown, Row } from "react-bootstrap";
 import { useTranslation } from "react-i18next";
 import { Link, Outlet, useNavigate } from "react-router-dom";
 import "./protected.layout.scss";
@@ -71,29 +71,35 @@ export const ProtectedLayout = () => {
 
   const HorizontalNavbar = () => {
     return (
-      <nav className="bg-white border-bottom border-dark py-2 d-flex align-items-center z-3 position-relative">
-        <Link to="/"><img src={logo} className="mx-4 me-5" width={25} alt="logo" /></Link>
-        <Link className={"head-links" + handleActiveLink(DEVICE_URL)} to="/">{t('protected.link.device_list')}</Link>
-        <Link className={"head-links" + handleActiveLink('/map')} to="/">{t('protected.link.map')}</Link>
-        <Link className={"head-links" + handleActiveLink('/configuration_management')} to="/">{t('protected.link.configuration_mgmt')}</Link>
+      <Container fluid>
+        <Row>
+          <Col>
+            <nav id="navbar" className="bg-white mx-4 mt-4 d-flex align-items-center c-box">
+              <Link to="/"><img src={logo} className="mx-4" width={45} alt="logo" /></Link>
+              <Link className={"head-links" + handleActiveLink(DEVICE_URL)} to="/">{t('protected.link.device_list')}</Link>
+              <Link className={"head-links" + handleActiveLink('/map')} to="/">{t('protected.link.map')}</Link>
+              <Link className={"head-links" + handleActiveLink('/configuration_management')} to="/">{t('protected.link.configuration_mgmt')}</Link>
 
-        <Dropdown className="ms-auto px-3">
-          <Dropdown.Toggle as={UserIconToggle}>
-            <FontAwesomeIcon icon={faCircleUser} className="clickable" size="2x" />
-          </Dropdown.Toggle>
+              <Dropdown className="ms-auto px-3">
+                <Dropdown.Toggle as={UserIconToggle}>
+                  <FontAwesomeIcon icon={faCircleUser} className="clickable" size="2x" />
+                </Dropdown.Toggle>
 
-          <Dropdown.Menu as={UserIconMenu}>
-            <Dropdown.Item eventKey="1">{user?.name}</Dropdown.Item>
-            <hr />
-            <Dropdown.Item eventKey="2">
-              <Link className="text-decoration-none text-reset" to="/">{t('protected.link.settings')}</Link>
-            </Dropdown.Item>
-            <Dropdown.Item eventKey="3" onClick={logout}>
-              <Link className="text-decoration-none text-reset" to="/"><FontAwesomeIcon className="clickable" icon={faRightFromBracket} />{t('protected.link.settings')}</Link>
-            </Dropdown.Item>
-          </Dropdown.Menu>
-        </Dropdown>
-      </nav>
+                <Dropdown.Menu as={UserIconMenu}>
+                  <Dropdown.Item eventKey="1">{user?.name}</Dropdown.Item>
+                  <hr />
+                  <Dropdown.Item eventKey="2">
+                    <Link className="text-decoration-none text-reset" to="/">{t('protected.link.settings')}</Link>
+                  </Dropdown.Item>
+                  <Dropdown.Item eventKey="3" onClick={logout}>
+                    <Link className="text-decoration-none text-reset" to="/"><FontAwesomeIcon className="clickable" icon={faRightFromBracket} /><span className="ms-1">{t('global.menu_item.logout')}</span></Link>
+                  </Dropdown.Item>
+                </Dropdown.Menu>
+              </Dropdown>
+            </nav>
+          </Col>
+        </Row>
+      </Container>
     )
   }
 
diff --git a/react-ui/src/shared/style/box.scss b/react-ui/src/shared/style/box.scss
index 934861a2b..418fe4af0 100755
--- a/react-ui/src/shared/style/box.scss
+++ b/react-ui/src/shared/style/box.scss
@@ -20,11 +20,11 @@ $border-width: 2px;
             border-box;
     border: $border-width solid transparent;
 
-    box-shadow: 0px 1px 2px rgba(map-get($theme-colors, "dark"), 0.12);
+    box-shadow: $box-shadow;
 }
 
 .abstract-box {
-    padding: 16px $box-padding;
+    padding: $box-padding;
     font-size: 0.9em;
     border-radius: calc($border-radius / 2);
 }
diff --git a/react-ui/src/shared/style/colors.scss b/react-ui/src/shared/style/colors.scss
index d91ffb44e..29c971f86 100755
--- a/react-ui/src/shared/style/colors.scss
+++ b/react-ui/src/shared/style/colors.scss
@@ -8,4 +8,6 @@ $theme-colors: (
   "black": #000000
 );
 
+$box-shadow: 0px 4px 8px rgba(map-get($theme-colors, "primary"), 0.2);
+
 @import "/node_modules/bootstrap/scss/bootstrap";
-- 
GitLab


From 7725832e23dd62eb7e2f42892aa179cc309219db Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@stud.h-da.de>
Date: Fri, 10 Jan 2025 19:45:07 +0100
Subject: [PATCH 35/79] (ui): implement movable box containers

---
 react-ui/package.json                         |  2 +
 .../src/components/devices/view/device.scss   |  5 --
 .../devices/view/device.view.table.tsx        |  1 +
 .../components/devices/view/device.view.tsx   | 50 ++++++++----
 react-ui/src/index.scss                       |  2 +-
 .../layouts/grid.layout/grid.layout.scss      | 81 +++++++++++++++++++
 .../layouts/grid.layout/grid.layout.tsx       | 61 ++++++++++++++
 .../protected.layout/protected.layout.tsx     | 10 +--
 react-ui/src/shared/style/box.scss            | 35 +++++++-
 react-ui/yarn.lock                            | 54 ++++++++++++-
 10 files changed, 268 insertions(+), 33 deletions(-)
 create mode 100644 react-ui/src/shared/layouts/grid.layout/grid.layout.scss
 create mode 100644 react-ui/src/shared/layouts/grid.layout/grid.layout.tsx

diff --git a/react-ui/package.json b/react-ui/package.json
index 30db7c97c..1f742d78d 100755
--- a/react-ui/package.json
+++ b/react-ui/package.json
@@ -14,6 +14,7 @@
         "@fortawesome/react-fontawesome": "^0.2.2",
         "@fullhuman/postcss-purgecss": "^7.0.2",
         "@reduxjs/toolkit": "^2.2.4",
+        "@types/react-grid-layout": "^1.3.5",
         "@vitejs/plugin-react": "^4.2.1",
         "bootstrap": "^5.3.3",
         "crypto-js": "^4.2.0",
@@ -24,6 +25,7 @@
         "react-bootstrap": "^2.10.2",
         "react-dom": "^18.3.1",
         "react-error-boundary": "^4.1.2",
+        "react-grid-layout": "^1.5.0",
         "react-i18next": "^15.0.0",
         "react-redux": "^9.1.2",
         "react-router-dom": "^6.23.1",
diff --git a/react-ui/src/components/devices/view/device.scss b/react-ui/src/components/devices/view/device.scss
index 866ce81eb..8d4099fc8 100755
--- a/react-ui/src/components/devices/view/device.scss
+++ b/react-ui/src/components/devices/view/device.scss
@@ -24,11 +24,6 @@
     }
 }
 
-.c-box {
-    padding: 2em !important;
-    padding-top: 1em !important;
-}
-
 .border-right {
     $border-padding: 2em;
 
diff --git a/react-ui/src/components/devices/view/device.view.table.tsx b/react-ui/src/components/devices/view/device.view.table.tsx
index 8800010e2..1f7221ead 100755
--- a/react-ui/src/components/devices/view/device.view.table.tsx
+++ b/react-ui/src/components/devices/view/device.view.table.tsx
@@ -49,6 +49,7 @@ export const DeviceViewTable = (searchRef: MutableRefObject<HTMLInputElement>) =
                     </OverlayTrigger>
                     <td data-copy-value={username} dangerouslySetInnerHTML={{ __html: search ? insertMarkTags(username, search) : DOMPurify.sanitize(username) }}></td>
                 </tr>
+
             )
         })
     }, [devices, searchRef, pnds, selectedDevice, trClickHandler]);
diff --git a/react-ui/src/components/devices/view/device.view.tsx b/react-ui/src/components/devices/view/device.view.tsx
index 4ef007327..f705aa4eb 100755
--- a/react-ui/src/components/devices/view/device.view.tsx
+++ b/react-ui/src/components/devices/view/device.view.tsx
@@ -1,3 +1,6 @@
+import { faGripVertical } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { GridLayout } from '@layout/grid.layout/grid.layout';
 import { useRef } from 'react';
 import { Button, Col, Container, Form, Nav, NavLink, Row } from 'react-bootstrap';
 import { useTranslation } from 'react-i18next';
@@ -13,12 +16,15 @@ const DeviceView = () => {
 
     return (
         <div className='m-4 pt-4'>
-            <Container fluid>
-                <Row>
-                    <Col lg={5} sm={12}>
-                        <Container className='bg-white c-box'>
+            <GridLayout>
+                <>
+                    <div key="device-list">
+                        <Container className='c-box hoverable h-100'>
+                            <FontAwesomeIcon icon={faGripVertical} className="drag-handle" />
                             <Row>
-                                <Col sm={12} className='mt-4'><h3 className='text-black-50'>{t('device.title')}</h3></Col>
+                                <Col sm={12} className='mt-4'>
+                                    <h3 className='text-black-50'>{t('device.title')}</h3>
+                                </Col>
                             </Row>
 
                             <Row className='align-items-center'>
@@ -38,14 +44,26 @@ const DeviceView = () => {
                                 </Col>
                             </Row>
                         </Container>
-                    </Col>
-                    <Col xs={12} lg={7} className='mt-5 mt-lg-0'>
-                        <Container className='bg-white c-box'>
+                    </div>
+
+                    <div key="device-details">
+                        <Container className='c-box hoverable h-100'>
+                            <FontAwesomeIcon icon={faGripVertical} className="drag-handle" />
                             <Row>
                                 <Col xs={12} className='mt-4'>
                                     <Nav className='justify-content-around'>
-                                        <NavLink className={handleActiveTabLink(DeviceViewTabValues.METADATA) + " tab-links"} onClick={() => setActiveTab(DeviceViewTabValues.METADATA)}>{t('device.tabs.metadata.title')}</NavLink>
-                                        <NavLink className={handleActiveTabLink(DeviceViewTabValues.YANGMODEL) + " tab-links"} onClick={() => setActiveTab(DeviceViewTabValues.YANGMODEL)}>{t('device.tabs.yang_model.title')}</NavLink>
+                                        <NavLink
+                                            className={handleActiveTabLink(DeviceViewTabValues.METADATA) + " tab-links"}
+                                            onClick={() => setActiveTab(DeviceViewTabValues.METADATA)}
+                                        >
+                                            {t('device.tabs.metadata.title')}
+                                        </NavLink>
+                                        <NavLink
+                                            className={handleActiveTabLink(DeviceViewTabValues.YANGMODEL) + " tab-links"}
+                                            onClick={() => setActiveTab(DeviceViewTabValues.YANGMODEL)}
+                                        >
+                                            {t('device.tabs.yang_model.title')}
+                                        </NavLink>
                                     </Nav>
                                 </Col>
                             </Row>
@@ -56,11 +74,11 @@ const DeviceView = () => {
                                 </Col>
                             </Row>
                         </Container>
-                    </Col>
-                </Row>
-            </Container>
+                    </div>
+                </>
+            </GridLayout>
         </div>
-    )
-}
+    );
+};
 
-export default DeviceView
+export default DeviceView;
\ No newline at end of file
diff --git a/react-ui/src/index.scss b/react-ui/src/index.scss
index 8dd280e64..5c9f184b7 100755
--- a/react-ui/src/index.scss
+++ b/react-ui/src/index.scss
@@ -1,4 +1,4 @@
-@import './shared/style/index.scss';
+@import "./shared/style/index.scss";
 
 body {
     margin: 0;
diff --git a/react-ui/src/shared/layouts/grid.layout/grid.layout.scss b/react-ui/src/shared/layouts/grid.layout/grid.layout.scss
new file mode 100644
index 000000000..c90375d37
--- /dev/null
+++ b/react-ui/src/shared/layouts/grid.layout/grid.layout.scss
@@ -0,0 +1,81 @@
+@import "/src/shared/style/colors.scss";
+
+.drag-handle {
+    position: absolute;
+    top: 0;
+    right: 0;
+    padding: 10px;
+    cursor: grab;
+    color: map-get($theme-colors, "dark");
+    background-color: lighten(map-get($theme-colors, primary), 38%);
+    border-radius: 0 0.25rem 0 0.25rem;
+    border-left: 1px solid lighten(map-get($theme-colors, dark), 35%);
+    border-bottom: 1px solid lighten(map-get($theme-colors, dark), 35%);
+    z-index: 10;
+
+    &:hover {
+        color: map-get($theme-colors, primary);
+        background-color: lighten(map-get($theme-colors, primary), 35%);
+    }
+
+    &:active {
+        cursor: grabbing;
+    }
+}
+
+.react-grid-item {
+    min-height: 600px !important;
+
+    &.react-draggable-dragging {
+        z-index: 100;
+
+        .drag-handle {
+            cursor: grabbing;
+        }
+    }
+}
+
+.react-grid-layout {
+    width: 100% !important;
+}
+
+.react-grid-item.react-grid-placeholder {
+    background: lighten(map-get($theme-colors, primary), 30%) !important;
+    opacity: 0.2;
+    transition-duration: 100ms;
+    z-index: 2;
+    border-radius: 4px;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    -o-user-select: none;
+    user-select: none;
+}
+
+.react-grid-item {
+    /* Hide resize handle by default */
+    .react-resizable-handle-se {
+        opacity: 0;
+        transition: opacity 0.2s ease-in-out;
+    }
+
+    /* Show resize handle on container hover */
+    &:hover .react-resizable-handle-se {
+        opacity: 1;
+    }
+}
+
+/* Style the resize handle */
+.react-resizable-handle-se {
+    position: absolute;
+    right: 0;
+    bottom: 0;
+    width: 20px;
+    height: 20px;
+    background-image: url("data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2IDYiPjxwYXRoIGQ9Ik02IDZIMHYtNmg2djZ6TTUgMUgxdjRoNFYxeiIgZmlsbD0iIzk5OTk5OSIvPjwvc3ZnPg==");
+    background-position: bottom right;
+    background-repeat: no-repeat;
+    background-size: 10px 10px;
+    cursor: se-resize;
+    z-index: 10;
+}
diff --git a/react-ui/src/shared/layouts/grid.layout/grid.layout.tsx b/react-ui/src/shared/layouts/grid.layout/grid.layout.tsx
new file mode 100644
index 000000000..c184e655b
--- /dev/null
+++ b/react-ui/src/shared/layouts/grid.layout/grid.layout.tsx
@@ -0,0 +1,61 @@
+import React, { ReactElement, useEffect, useState } from 'react';
+import { Responsive, WidthProvider } from 'react-grid-layout';
+import 'react-grid-layout/css/styles.css';
+import 'react-resizable/css/styles.css';
+import './grid.layout.scss';
+
+const ResponsiveGridLayout = WidthProvider(Responsive);
+
+interface GridLayoutProps {
+    children: ReactElement;
+}
+
+export const GridLayout: React.FC<GridLayoutProps> = ({ children }) => {
+    const rowHeight = 50;
+    const [mounted, setMounted] = useState(false);
+    const layouts = {
+        lg: [
+            { i: 'device-list', x: 0, y: 0, w: 1, h: 1, minW: 1, minH: 1 },
+            { i: 'device-details', x: 2, y: 0, w: 2, h: 1, minW: 2, minH: 1 }
+        ]
+    };
+
+    useEffect(() => {
+        setMounted(true);
+        // Force layout recalculation after mount
+        window.dispatchEvent(new Event('resize'));
+    }, []);
+
+    const gridItems = React.Children.map(children.props.children, (child, index) => {
+        if (!React.isValidElement(child)) return null;
+
+        return React.cloneElement(child, {
+            key: index === 0 ? 'device-list' : 'device-details',
+            'data-grid': layouts.lg[index]
+        });
+    });
+
+    return (
+        <div style={{ display: mounted ? 'block' : 'none' }}>
+            <ResponsiveGridLayout
+                className="layout"
+                layouts={layouts}
+                breakpoints={{ lg: 996, sm: 480 }}
+                cols={{ lg: 4, sm: 3 }}
+                rowHeight={rowHeight}
+                margin={[20, 20]}
+                draggableHandle=".drag-handle"
+                isDraggable={true}
+                isResizable={true}
+                preventCollision={true}
+                compactType={null}
+                useCSSTransforms={mounted}
+                resizeHandles={['se']} // Only show resize handle in bottom right corner
+            >
+                {gridItems}
+            </ResponsiveGridLayout>
+        </div>
+    );
+};
+
+export default GridLayout;
\ No newline at end of file
diff --git a/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx b/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx
index 5dc565455..dbcb49192 100755
--- a/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx
+++ b/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx
@@ -104,11 +104,9 @@ export const ProtectedLayout = () => {
   }
 
   return (
-    <div>
-      <MenuProvider>
-        {HorizontalNavbar()}
-        <Outlet />
-      </MenuProvider>
-    </div>
+    <MenuProvider>
+      {HorizontalNavbar()}
+      <Outlet />
+    </MenuProvider>
   )
 };
\ No newline at end of file
diff --git a/react-ui/src/shared/style/box.scss b/react-ui/src/shared/style/box.scss
index 418fe4af0..53158f515 100755
--- a/react-ui/src/shared/style/box.scss
+++ b/react-ui/src/shared/style/box.scss
@@ -1,26 +1,55 @@
 @import "./colors.scss";
 
 $box-padding: 10px;
-$border-radius: 20px;
+$border-radius: 0.25em;
 $border-width: 2px;
+$transition-duration: 0.3s;
 
 .c-box {
     padding: $box-padding;
     background-color: white;
     position: relative;
     border-radius: $border-radius;
+    transition: box-shadow $transition-duration ease-in-out;
 
     background:
         linear-gradient(white, white) padding-box,
         linear-gradient(
                 180deg,
-                rgba(map-get($theme-colors, "primary"), 0.3) 0%,
+                rgba(map-get($theme-colors, "primary"), 0.4) 0%,
+                rgba(map-get($theme-colors, "primary"), 0.2) 40%,
                 rgba(map-get($theme-colors, "primary"), 0.1) 100%
             )
             border-box;
     border: $border-width solid transparent;
-
     box-shadow: $box-shadow;
+
+    &::before {
+        content: "";
+        position: absolute;
+        top: -$border-width;
+        left: -$border-width;
+        right: -$border-width;
+        bottom: -$border-width;
+        background: linear-gradient(
+            180deg,
+            rgba(map-get($theme-colors, "primary"), 0.4) 0%,
+            rgba(map-get($theme-colors, "primary"), 0.2) 60%,
+            rgba(map-get($theme-colors, "primary"), 0.1) 100%
+        );
+        border-radius: inherit;
+        z-index: -1;
+        opacity: 0;
+        transition: opacity $transition-duration ease-in-out;
+    }
+
+    &:hover {
+        box-shadow: 0 0.5rem 1rem rgba(map-get($theme-colors, "primary"), 0.2);
+
+        &::before {
+            opacity: 1;
+        }
+    }
 }
 
 .abstract-box {
diff --git a/react-ui/yarn.lock b/react-ui/yarn.lock
index ec57231a8..db8fb7d3c 100755
--- a/react-ui/yarn.lock
+++ b/react-ui/yarn.lock
@@ -2593,6 +2593,13 @@
   resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.3.tgz#3654138d0da1b0c7916f6ed0dc1cc2b576d47650"
   integrity sha512-uTYkxTLkYp41nq/ULXyXMtkNT1vu5fXJoqad6uTNCOGat5t9cLgF4vMNLBXsTOXpdOI44XzKPY1M5RRm0bQHuw==
 
+"@types/react-grid-layout@^1.3.5":
+  version "1.3.5"
+  resolved "https://registry.yarnpkg.com/@types/react-grid-layout/-/react-grid-layout-1.3.5.tgz#f4b52bf27775290ee0523214be0987be14e66823"
+  integrity sha512-WH/po1gcEcoR6y857yAnPGug+ZhkF4PaTUxgAbwfeSH/QOgVSakKHBXoPGad/sEznmkiaK3pqHk+etdWisoeBQ==
+  dependencies:
+    "@types/react" "*"
+
 "@types/react-transition-group@^4.4.6":
   version "4.4.11"
   resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.11.tgz#d963253a611d757de01ebb241143b1017d5d63d5"
@@ -3843,7 +3850,12 @@ cliui@^8.0.1:
     strip-ansi "^6.0.1"
     wrap-ansi "^7.0.0"
 
-clsx@^2.1.0:
+clsx@^1.1.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12"
+  integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
+
+clsx@^2.0.0, clsx@^2.1.0:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999"
   integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
@@ -5351,6 +5363,11 @@ fast-diff@^1.1.2:
   resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0"
   integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==
 
+fast-equals@^4.0.3:
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-4.0.3.tgz#72884cc805ec3c6679b99875f6b7654f39f0e8c7"
+  integrity sha512-G3BSX9cfKttjr+2o1O22tYMLq0DPluZnYtq1rXumE1SpL/F/SLIfHx08WYQoWSIpeMYf8sRbJ8++71+v6Pnxfg==
+
 fast-glob@^3.2.9, fast-glob@^3.3.2:
   version "3.3.2"
   resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129"
@@ -8680,7 +8697,7 @@ prop-types-extra@^1.1.0:
     react-is "^16.3.2"
     warning "^4.0.0"
 
-prop-types@^15.6.2, prop-types@^15.8.1:
+prop-types@15.x, prop-types@^15.6.2, prop-types@^15.8.1:
   version "15.8.1"
   resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
   integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
@@ -8838,6 +8855,14 @@ react-dom@^18.3.1:
     loose-envify "^1.1.0"
     scheduler "^0.23.2"
 
+react-draggable@^4.0.3, react-draggable@^4.4.5:
+  version "4.4.6"
+  resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.4.6.tgz#63343ee945770881ca1256a5b6fa5c9f5983fe1e"
+  integrity sha512-LtY5Xw1zTPqHkVmtM3X8MUOxNDOUhv/khTgBgrUvwaS064bwVvxT+q5El0uUFNx5IEPKXuRejr7UqLwBIg5pdw==
+  dependencies:
+    clsx "^1.1.1"
+    prop-types "^15.8.1"
+
 react-error-boundary@^4.1.2:
   version "4.1.2"
   resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-4.1.2.tgz#bc750ad962edb8b135d6ae922c046051eb58f289"
@@ -8850,6 +8875,18 @@ react-error-overlay@^6.0.11:
   resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb"
   integrity sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==
 
+react-grid-layout@^1.5.0:
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/react-grid-layout/-/react-grid-layout-1.5.0.tgz#b6cc9412b58cf8226aebc0df7673d6fa782bdee2"
+  integrity sha512-WBKX7w/LsTfI99WskSu6nX2nbJAUD7GD6nIXcwYLyPpnslojtmql2oD3I2g5C3AK8hrxIarYT8awhuDIp7iQ5w==
+  dependencies:
+    clsx "^2.0.0"
+    fast-equals "^4.0.3"
+    prop-types "^15.8.1"
+    react-draggable "^4.4.5"
+    react-resizable "^3.0.5"
+    resize-observer-polyfill "^1.5.1"
+
 react-i18next@^15.0.0:
   version "15.1.4"
   resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-15.1.4.tgz#65c03c31a5e42202000652e163f22f23a9306a60"
@@ -8896,6 +8933,14 @@ react-refresh@^0.14.2:
   resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9"
   integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==
 
+react-resizable@^3.0.5:
+  version "3.0.5"
+  resolved "https://registry.yarnpkg.com/react-resizable/-/react-resizable-3.0.5.tgz#362721f2efbd094976f1780ae13f1ad7739786c1"
+  integrity sha512-vKpeHhI5OZvYn82kXOs1bC8aOXktGU5AmKAgaZS4F5JPburCtbmDPqE7Pzp+1kN4+Wb81LlF33VpGwWwtXem+w==
+  dependencies:
+    prop-types "15.x"
+    react-draggable "^4.0.3"
+
 react-router-dom@^6.23.1:
   version "6.28.0"
   resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.28.0.tgz#f73ebb3490e59ac9f299377062ad1d10a9f579e6"
@@ -9189,6 +9234,11 @@ reselect@^5.1.0:
   resolved "https://registry.yarnpkg.com/reselect/-/reselect-5.1.1.tgz#c766b1eb5d558291e5e550298adb0becc24bb72e"
   integrity sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==
 
+resize-observer-polyfill@^1.5.1:
+  version "1.5.1"
+  resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
+  integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
+
 resolve-cwd@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
-- 
GitLab


From e59acfcd4d8a41a4508b2963e649c845a5374d29 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Mon, 13 Jan 2025 07:53:54 +0000
Subject: [PATCH 36/79] [renovate] Update module go.mongodb.org/mongo-driver to
 v1.17.2

See merge request danet/gosdn!1147

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 2 +-
 go.sum | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/go.mod b/go.mod
index 16daa3076..ef618f305 100644
--- a/go.mod
+++ b/go.mod
@@ -22,7 +22,7 @@ require (
 	github.com/spf13/viper v1.19.0
 	github.com/stretchr/objx v0.5.2 // indirect
 	github.com/stretchr/testify v1.10.0
-	go.mongodb.org/mongo-driver v1.17.1
+	go.mongodb.org/mongo-driver v1.17.2
 	golang.org/x/sync v0.10.0
 	google.golang.org/grpc v1.69.2
 	google.golang.org/protobuf v1.36.2
diff --git a/go.sum b/go.sum
index d1247f175..fc4bb17f3 100644
--- a/go.sum
+++ b/go.sum
@@ -406,6 +406,8 @@ go.mongodb.org/mongo-driver v1.17.0 h1:Hp4q2MCjvY19ViwimTs00wHi7G4yzxh4/2+nTx8r4
 go.mongodb.org/mongo-driver v1.17.0/go.mod h1:wwWm/+BuOddhcq3n68LKRmgk2wXzmF6s0SFOa0GINL4=
 go.mongodb.org/mongo-driver v1.17.1 h1:Wic5cJIwJgSpBhe3lx3+/RybR5PiYRMpVFgO7cOHyIM=
 go.mongodb.org/mongo-driver v1.17.1/go.mod h1:wwWm/+BuOddhcq3n68LKRmgk2wXzmF6s0SFOa0GINL4=
+go.mongodb.org/mongo-driver v1.17.2 h1:gvZyk8352qSfzyZ2UMWcpDpMSGEr1eqE4T793SqyhzM=
+go.mongodb.org/mongo-driver v1.17.2/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
 go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
-- 
GitLab


From 91b6db7bbc1fe5c5bc4b21d1fdf39bec3cdce699 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Mon, 13 Jan 2025 08:04:48 +0000
Subject: [PATCH 37/79] [renovate] Update renovate/renovate Docker tag to
 v39.106.0

See merge request danet/gosdn!1153

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 .gitlab/ci/.renovate.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab/ci/.renovate.yml b/.gitlab/ci/.renovate.yml
index 03f8fddfa..4d7442638 100644
--- a/.gitlab/ci/.renovate.yml
+++ b/.gitlab/ci/.renovate.yml
@@ -1,7 +1,7 @@
 renovate:
     stage: tools
 
-    image: renovate/renovate:39.91.3
+    image: renovate/renovate:39.106.0
 
     variables:
         LOG_LEVEL: debug
-- 
GitLab


From 671ed78c14074082c33ea57b412e89e457178d6e Mon Sep 17 00:00:00 2001
From: Fabian Seidl <fabian.seidl@h-da.de>
Date: Mon, 13 Jan 2025 09:24:45 +0000
Subject: [PATCH 38/79] Bump golangci-lint in Makefile to version 1.63.4 and
 fix deprecated output option

See merge request danet/gosdn!1140
---
 .golangci.yml | 2 +-
 Makefile      | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.golangci.yml b/.golangci.yml
index cdd404e55..42bb6ac6b 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -14,13 +14,13 @@ output:
       - format: colored-line-number
     print-issued-lines: true
     print-linter-name: true
-    uniq-by-line: true
     path-prefix: ""
 
 issues:
     exclude-use-default: false
     max-issues-per-linter: 0
     max-same-issues: 0
+    uniq-by-line: true
     exclude-files:
         - http.go
     # directories to be ignored by linters
diff --git a/Makefile b/Makefile
index 888644abe..0cd0ed66d 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,7 @@ PLUGIN_NAME= bundled_plugin.zip
 
 # Tool Versions
 GOTESTSUM_VERSION=v1.8.1
-GOLANGCI_LINT_VERSION=v1.62.0
+GOLANGCI_LINT_VERSION=v1.63.4
 MOCKERY_VERSION=v2.20.0
 YGOT_GENERATOR_VERSION=v0.27.0
 YGOT_GENERATOR_GENERATOR_VERSION=v0.0.4
-- 
GitLab


From d57f811bde015249e6f9fe7803655c4ce6aa5261 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Tue, 14 Jan 2025 08:19:07 +0000
Subject: [PATCH 39/79] [renovate] Update module github.com/golang/glog to
 v1.2.4

See merge request danet/gosdn!1154

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 2 +-
 go.sum | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/go.mod b/go.mod
index ef618f305..05dac3b36 100644
--- a/go.mod
+++ b/go.mod
@@ -41,7 +41,7 @@ require (
 	github.com/fsnotify/fsnotify v1.7.0 // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
 	github.com/golang-jwt/jwt v3.2.2+incompatible
-	github.com/golang/glog v1.2.3
+	github.com/golang/glog v1.2.4
 	github.com/golang/protobuf v1.5.4
 	github.com/golang/snappy v0.0.4 // indirect
 	github.com/gookit/color v1.5.4 // indirect
diff --git a/go.sum b/go.sum
index fc4bb17f3..8ed1358ae 100644
--- a/go.sum
+++ b/go.sum
@@ -132,6 +132,8 @@ github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY=
 github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
 github.com/golang/glog v1.2.3 h1:oDTdz9f5VGVVNGu/Q7UXKWYsD0873HXLHdJUNBsSEKM=
 github.com/golang/glog v1.2.3/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
+github.com/golang/glog v1.2.4 h1:CNNw5U8lSiiBk7druxtSHHTsRWcxKoac6kZKm2peBBc=
+github.com/golang/glog v1.2.4/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
 github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
 github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-- 
GitLab


From 299c784b2ebabc01e26a4029906b0249e8ef57ae Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Tue, 14 Jan 2025 08:29:32 +0000
Subject: [PATCH 40/79] [renovate] Update module google.golang.org/grpc to
 v1.69.4

See merge request danet/gosdn!1155

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 2 +-
 go.sum | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/go.mod b/go.mod
index 05dac3b36..084198b91 100644
--- a/go.mod
+++ b/go.mod
@@ -24,7 +24,7 @@ require (
 	github.com/stretchr/testify v1.10.0
 	go.mongodb.org/mongo-driver v1.17.2
 	golang.org/x/sync v0.10.0
-	google.golang.org/grpc v1.69.2
+	google.golang.org/grpc v1.69.4
 	google.golang.org/protobuf v1.36.2
 	gopkg.in/yaml.v3 v3.0.1
 )
diff --git a/go.sum b/go.sum
index 8ed1358ae..e9fb90e36 100644
--- a/go.sum
+++ b/go.sum
@@ -659,6 +659,8 @@ google.golang.org/grpc v1.68.1 h1:oI5oTa11+ng8r8XMMN7jAOmWfPZWbYpCFaMUTACxkM0=
 google.golang.org/grpc v1.68.1/go.mod h1:+q1XYFJjShcqn0QZHvCyeR4CXPA+llXIeUIfIe00waw=
 google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU=
 google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
+google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A=
+google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
-- 
GitLab


From 7289637f33723cb0ef3c5bc7053bb0419b2c90b2 Mon Sep 17 00:00:00 2001
From: Fabian Seidl <fabian.seidl@h-da.de>
Date: Tue, 14 Jan 2025 14:11:30 +0000
Subject: [PATCH 41/79] Resolve "Improve subscription logging"

See merge request danet/gosdn!1156
---
 controller/nucleus/networkElementWatcher.go | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/controller/nucleus/networkElementWatcher.go b/controller/nucleus/networkElementWatcher.go
index 8b542d086..07ad775f2 100644
--- a/controller/nucleus/networkElementWatcher.go
+++ b/controller/nucleus/networkElementWatcher.go
@@ -200,6 +200,8 @@ func (n *NetworkElementWatcher) StopAndRemoveNetworkElementSubscription(subID uu
 // handleSubscribeResponse takes the subscribe response and additional information about the network element to distinguish
 // from which network element a subscribe response was sent including improved error handling.
 func (n *NetworkElementWatcher) handleSubscribeResponse(subscriptionInfo *transport.SubscriptionInformation, workerName string) {
+	log.Debugf("Received Subscribe response: MNE ID: %s, MNE Name: %s, SubResponse: %v", subscriptionInfo.NetworkElementID, subscriptionInfo.NetworkElementName, subscriptionInfo.SubResponse)
+
 	if subscriptionInfo.SubResponse == nil {
 		// Note: This needs proper error handling, no idea how yet. Simply logging would lead to spam in the console
 		// if the target that was subscribed to is not reachable anymore.
@@ -232,6 +234,11 @@ func (n *NetworkElementWatcher) handleSubscribeResponse(subscriptionInfo *transp
 func (n *NetworkElementWatcher) handleSubscribeResponseUpdate(resp *gpb.SubscribeResponse_Update, subscriptionInfo *transport.SubscriptionInformation) {
 	pathsAndValues := make(map[string]string, len(resp.Update.Update))
 
+	if resp.Update == nil || len(resp.Update.Update) == 0 {
+		log.Debugf("handleSubscribeResponseUpdate empty update or updates; Update: %v, InnerUpdates: %v", resp.Update, resp.Update.Update)
+		return
+	}
+
 	for _, update := range resp.Update.Update {
 		pathString, err := ygot.PathToString(update.Path)
 		if err != nil {
-- 
GitLab


From 9839c9bf1f2f12ef40a75a1bc7d3ed2ef1390853 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Tue, 14 Jan 2025 15:53:35 +0000
Subject: [PATCH 42/79] [renovate] Update renovate/renovate Docker tag to
 v39.107.0

See merge request danet/gosdn!1157

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 .gitlab/ci/.renovate.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab/ci/.renovate.yml b/.gitlab/ci/.renovate.yml
index 4d7442638..81070e9da 100644
--- a/.gitlab/ci/.renovate.yml
+++ b/.gitlab/ci/.renovate.yml
@@ -1,7 +1,7 @@
 renovate:
     stage: tools
 
-    image: renovate/renovate:39.106.0
+    image: renovate/renovate:39.107.0
 
     variables:
         LOG_LEVEL: debug
-- 
GitLab


From 7d17bc8826367497aa3dcd87951683f73926af74 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Wed, 15 Jan 2025 08:22:44 +0000
Subject: [PATCH 43/79] [renovate] Update module
 github.com/bufbuild/protovalidate-go to v0.8.2

See merge request danet/gosdn!1131

Co-authored-by: Fabian Seidl <fabian.seidl@h-da.de>
Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 controller/northbound/server/auth_test.go     | 16 ++++-
 controller/northbound/server/role_test.go     | 71 ++++++++++++++++---
 controller/northbound/server/topology_test.go | 63 ++++++++++++++--
 controller/northbound/server/user_test.go     | 30 +++++++-
 controller/northbound/server/utils_test.go    |  3 +-
 go.mod                                        |  4 +-
 go.sum                                        |  4 ++
 7 files changed, 169 insertions(+), 22 deletions(-)

diff --git a/controller/northbound/server/auth_test.go b/controller/northbound/server/auth_test.go
index e5c9e7389..956ef2be1 100644
--- a/controller/northbound/server/auth_test.go
+++ b/controller/northbound/server/auth_test.go
@@ -89,7 +89,13 @@ func TestAuth_Login(t *testing.T) {
 			wantErr: true,
 			validationErrors: []*validate.Violation{
 				{
-					FieldPath:    stringToPointer("username"),
+					Field: &validate.FieldPath{
+						Elements: []*validate.FieldPathElement{
+							{
+								FieldName: stringToPointer("username"),
+							},
+						},
+					},
 					ConstraintId: stringToPointer("required"),
 					Message:      stringToPointer("value is required"),
 				}},
@@ -160,7 +166,13 @@ func TestAuth_Logout(t *testing.T) {
 			wantErr: true,
 			validationErrors: []*validate.Violation{
 				{
-					FieldPath:    stringToPointer("username"),
+					Field: &validate.FieldPath{
+						Elements: []*validate.FieldPathElement{
+							{
+								FieldName: stringToPointer("username"),
+							},
+						},
+					},
 					ConstraintId: stringToPointer("required"),
 					Message:      stringToPointer("value is required"),
 				}},
diff --git a/controller/northbound/server/role_test.go b/controller/northbound/server/role_test.go
index bb787a416..2d75e0678 100644
--- a/controller/northbound/server/role_test.go
+++ b/controller/northbound/server/role_test.go
@@ -84,10 +84,20 @@ func TestRole_CreateRoles(t *testing.T) {
 			wantErr: true,
 			validationErrors: []*validate.Violation{
 				{
-					FieldPath:    stringToPointer("roles[0].name"),
+					Field: &validate.FieldPath{
+						Elements: []*validate.FieldPathElement{
+							{
+								FieldName: stringToPointer("roles"),
+							},
+							{
+								FieldName: stringToPointer("name"),
+							},
+						},
+					},
 					ConstraintId: stringToPointer("string.min_len"),
 					Message:      stringToPointer("value length must be at least 3 characters"),
-				}},
+				},
+			},
 		},
 		{
 			name: "role with too short description should fail",
@@ -105,7 +115,16 @@ func TestRole_CreateRoles(t *testing.T) {
 			want:    &apb.CreateRolesResponse{},
 			wantErr: true,
 			validationErrors: []*validate.Violation{{
-				FieldPath:    stringToPointer("roles[0].description"),
+				Field: &validate.FieldPath{
+					Elements: []*validate.FieldPathElement{
+						{
+							FieldName: stringToPointer("roles"),
+						},
+						{
+							FieldName: stringToPointer("description"),
+						},
+					},
+				},
 				ConstraintId: stringToPointer("string.min_len"),
 				Message:      stringToPointer("value length must be at least 3 characters"),
 			}},
@@ -181,7 +200,13 @@ func TestRole_GetRole(t *testing.T) {
 			wantErr: true,
 			validationErrors: []*validate.Violation{
 				{
-					FieldPath:    stringToPointer("role_name"),
+					Field: &validate.FieldPath{
+						Elements: []*validate.FieldPathElement{
+							{
+								FieldName: stringToPointer("role_name"),
+							},
+						},
+					},
 					ConstraintId: stringToPointer("required"),
 					Message:      stringToPointer("value is required"),
 				},
@@ -355,7 +380,16 @@ func TestRole_UpdateRoles(t *testing.T) {
 			wantErr: true,
 			validationErrors: []*validate.Violation{
 				{
-					FieldPath:    stringToPointer("roles[0].name"),
+					Field: &validate.FieldPath{
+						Elements: []*validate.FieldPathElement{
+							{
+								FieldName: stringToPointer("roles"),
+							},
+							{
+								FieldName: stringToPointer("name"),
+							},
+						},
+					},
 					ConstraintId: stringToPointer("string.min_len"),
 					Message:      stringToPointer("value length must be at least 3 characters"),
 				},
@@ -379,7 +413,16 @@ func TestRole_UpdateRoles(t *testing.T) {
 			wantErr: true,
 			validationErrors: []*validate.Violation{
 				{
-					FieldPath:    stringToPointer("roles[0].description"),
+					Field: &validate.FieldPath{
+						Elements: []*validate.FieldPathElement{
+							{
+								FieldName: stringToPointer("roles"),
+							},
+							{
+								FieldName: stringToPointer("description"),
+							},
+						},
+					},
 					ConstraintId: stringToPointer("string.min_len"),
 					Message:      stringToPointer("value length must be at least 3 characters"),
 				},
@@ -456,12 +499,24 @@ func TestRole_DeletePermissionsForRole(t *testing.T) {
 			wantErr: true,
 			validationErrors: []*validate.Violation{
 				{
-					FieldPath:    stringToPointer("role_name"),
+					Field: &validate.FieldPath{
+						Elements: []*validate.FieldPathElement{
+							{
+								FieldName: stringToPointer("role_name"),
+							},
+						},
+					},
 					ConstraintId: stringToPointer("required"),
 					Message:      stringToPointer("value is required"),
 				},
 				{
-					FieldPath:    stringToPointer("permissions_to_delete"),
+					Field: &validate.FieldPath{
+						Elements: []*validate.FieldPathElement{
+							{
+								FieldName: stringToPointer("permissions_to_delete"),
+							},
+						},
+					},
 					ConstraintId: stringToPointer("required"),
 					Message:      stringToPointer("value is required"),
 				},
diff --git a/controller/northbound/server/topology_test.go b/controller/northbound/server/topology_test.go
index 44ce77b57..dea560a45 100644
--- a/controller/northbound/server/topology_test.go
+++ b/controller/northbound/server/topology_test.go
@@ -285,27 +285,72 @@ func TestTopology_AddLink(t *testing.T) {
 			wantErr: true,
 			validationErrors: []*validate.Violation{
 				{
-					FieldPath:    stringToPointer("link.name"),
+					Field: &validate.FieldPath{
+						Elements: []*validate.FieldPathElement{
+							{
+								FieldName: stringToPointer("link"),
+							},
+							{
+								FieldName: stringToPointer("name"),
+							},
+						},
+					},
 					ConstraintId: stringToPointer("string.min_len"),
 					Message:      stringToPointer("value length must be at least 1 characters"),
 				},
 				{
-					FieldPath:    stringToPointer("link.sourceNode"),
+					Field: &validate.FieldPath{
+						Elements: []*validate.FieldPathElement{
+							{
+								FieldName: stringToPointer("link"),
+							},
+							{
+								FieldName: stringToPointer("sourceNode"),
+							},
+						},
+					},
 					ConstraintId: stringToPointer("required"),
 					Message:      stringToPointer("value is required"),
 				},
 				{
-					FieldPath:    stringToPointer("link.targetNode"),
+					Field: &validate.FieldPath{
+						Elements: []*validate.FieldPathElement{
+							{
+								FieldName: stringToPointer("link"),
+							},
+							{
+								FieldName: stringToPointer("targetNode"),
+							},
+						},
+					},
 					ConstraintId: stringToPointer("required"),
 					Message:      stringToPointer("value is required"),
 				},
 				{
-					FieldPath:    stringToPointer("link.sourcePort"),
+					Field: &validate.FieldPath{
+						Elements: []*validate.FieldPathElement{
+							{
+								FieldName: stringToPointer("link"),
+							},
+							{
+								FieldName: stringToPointer("sourcePort"),
+							},
+						},
+					},
 					ConstraintId: stringToPointer("required"),
 					Message:      stringToPointer("value is required"),
 				},
 				{
-					FieldPath:    stringToPointer("link.targetPort"),
+					Field: &validate.FieldPath{
+						Elements: []*validate.FieldPathElement{
+							{
+								FieldName: stringToPointer("link"),
+							},
+							{
+								FieldName: stringToPointer("targetPort"),
+							},
+						},
+					},
 					ConstraintId: stringToPointer("required"),
 					Message:      stringToPointer("value is required"),
 				},
@@ -461,7 +506,13 @@ func TestTopology_DeleteLink(t *testing.T) {
 			wantErr: true,
 			validationErrors: []*validate.Violation{
 				{
-					FieldPath:    stringToPointer("id"),
+					Field: &validate.FieldPath{
+						Elements: []*validate.FieldPathElement{
+							{
+								FieldName: stringToPointer("id"),
+							},
+						},
+					},
 					ConstraintId: stringToPointer("required"),
 					Message:      stringToPointer("value is required"),
 				}},
diff --git a/controller/northbound/server/user_test.go b/controller/northbound/server/user_test.go
index 4a1c66327..9fcdf4d61 100644
--- a/controller/northbound/server/user_test.go
+++ b/controller/northbound/server/user_test.go
@@ -90,7 +90,16 @@ func TestUser_CreateUsers(t *testing.T) {
 			wantErr: true,
 			validationErrors: []*validate.Violation{
 				{
-					FieldPath:    stringToPointer("user[0].password"),
+					Field: &validate.FieldPath{
+						Elements: []*validate.FieldPathElement{
+							{
+								FieldName: stringToPointer("user"),
+							},
+							{
+								FieldName: stringToPointer("password"),
+							},
+						},
+					},
 					ConstraintId: stringToPointer("string.min_len"),
 					Message:      stringToPointer("value length must be at least 5 characters"),
 				}},
@@ -116,7 +125,16 @@ func TestUser_CreateUsers(t *testing.T) {
 			wantErr: true,
 			validationErrors: []*validate.Violation{
 				{
-					FieldPath:    stringToPointer("user[0].name"),
+					Field: &validate.FieldPath{
+						Elements: []*validate.FieldPathElement{
+							{
+								FieldName: stringToPointer("user"),
+							},
+							{
+								FieldName: stringToPointer("name"),
+							},
+						},
+					},
 					ConstraintId: stringToPointer("string.min_len"),
 					Message:      stringToPointer("value length must be at least 3 characters"),
 				}},
@@ -190,7 +208,13 @@ func TestUser_GetUser(t *testing.T) {
 			wantErr: true,
 			validationErrors: []*validate.Violation{
 				{
-					FieldPath:    stringToPointer("name"),
+					Field: &validate.FieldPath{
+						Elements: []*validate.FieldPathElement{
+							{
+								FieldName: stringToPointer("name"),
+							},
+						},
+					},
 					ConstraintId: stringToPointer("required"),
 					Message:      stringToPointer("value is required"),
 				}},
diff --git a/controller/northbound/server/utils_test.go b/controller/northbound/server/utils_test.go
index 7a4636caa..dd95d8f2e 100644
--- a/controller/northbound/server/utils_test.go
+++ b/controller/northbound/server/utils_test.go
@@ -23,7 +23,8 @@ func isEqualFieldPaths(violationFieldPath, errFieldPath *validate.FieldPath) boo
 	}
 
 	for i, elem := range violationFieldPath.GetElements() {
-		if elem != errFieldPath.GetElements()[i] {
+		errElem := errFieldPath.GetElements()[i]
+		if *elem.FieldName != *errElem.FieldName {
 			return false
 		}
 	}
diff --git a/go.mod b/go.mod
index 084198b91..9cbe7dabc 100644
--- a/go.mod
+++ b/go.mod
@@ -87,7 +87,7 @@ require (
 
 require (
 	buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.2-20241127180247-a33202765966.1
-	github.com/bufbuild/protovalidate-go v0.7.3
+	github.com/bufbuild/protovalidate-go v0.8.2
 	github.com/hashicorp/go-multierror v1.1.1
 	github.com/hashicorp/go-plugin v1.4.10
 	github.com/lesismal/nbio v1.5.12
@@ -103,7 +103,7 @@ require (
 	github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
 	github.com/containerd/console v1.0.3 // indirect
 	github.com/fatih/color v1.15.0 // indirect
-	github.com/google/cel-go v0.22.0 // indirect
+	github.com/google/cel-go v0.22.1 // indirect
 	github.com/hashicorp/errwrap v1.1.0 // indirect
 	github.com/hashicorp/go-hclog v1.5.0 // indirect
 	github.com/hashicorp/yamux v0.1.1 // indirect
diff --git a/go.sum b/go.sum
index e9fb90e36..7a355f78a 100644
--- a/go.sum
+++ b/go.sum
@@ -79,6 +79,8 @@ github.com/bufbuild/protovalidate-go v0.7.2 h1:UuvKyZHl5p7u3ztEjtRtqtDxOjRKX5VUO
 github.com/bufbuild/protovalidate-go v0.7.2/go.mod h1:PHV5pFuWlRzdDW02/cmVyNzdiQ+RNNwo7idGxdzS7o4=
 github.com/bufbuild/protovalidate-go v0.7.3 h1:kKnoSueygR3xxppvuBpm9SEwIsP359MMRfMBGmRByPg=
 github.com/bufbuild/protovalidate-go v0.7.3/go.mod h1:CFv34wMqiBzAHdQ4q/tWYi9ILFYKuaC3/4zh6eqdUck=
+github.com/bufbuild/protovalidate-go v0.8.2 h1:sgzXHkHYP6HnAsL2Rd3I1JxkYUyEQUv9awU1PduMxbM=
+github.com/bufbuild/protovalidate-go v0.8.2/go.mod h1:K6w8iPNAXBoIivVueSELbUeUl+MmeTQfCDSug85pn3M=
 github.com/c-bata/go-prompt v0.2.6 h1:POP+nrHE+DfLYx370bedwNhsqmpCUynWPxuHi0C5vZI=
 github.com/c-bata/go-prompt v0.2.6/go.mod h1:/LMAke8wD2FsNu9EXNdHxNLbd9MedkPnCdfpU9wwHfY=
 github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
@@ -156,6 +158,8 @@ github.com/google/cel-go v0.21.0 h1:cl6uW/gxN+Hy50tNYvI691+sXxioCnstFzLp2WO4GCI=
 github.com/google/cel-go v0.21.0/go.mod h1:rHUlWCcBKgyEk+eV03RPdZUekPp6YcJwV0FxuUksYxc=
 github.com/google/cel-go v0.22.0 h1:b3FJZxpiv1vTMo2/5RDUqAHPxkT8mmMfJIrq1llbf7g=
 github.com/google/cel-go v0.22.0/go.mod h1:BuznPXXfQDpXKWQ9sPW3TzlAJN5zzFe+i9tIs0yC4s8=
+github.com/google/cel-go v0.22.1 h1:AfVXx3chM2qwoSbM7Da8g8hX8OVSkBFwX+rz2+PcK40=
+github.com/google/cel-go v0.22.1/go.mod h1:BuznPXXfQDpXKWQ9sPW3TzlAJN5zzFe+i9tIs0yC4s8=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-- 
GitLab


From 6706a91a76994e8fdbc7551b4279fe74f6fef99a Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Wed, 15 Jan 2025 14:41:45 +0000
Subject: [PATCH 44/79] [renovate] Update module go.mongodb.org/mongo-driver to
 v2

See merge request danet/gosdn!1129

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 3 ++-
 go.sum | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/go.mod b/go.mod
index 9cbe7dabc..f48265086 100644
--- a/go.mod
+++ b/go.mod
@@ -22,7 +22,7 @@ require (
 	github.com/spf13/viper v1.19.0
 	github.com/stretchr/objx v0.5.2 // indirect
 	github.com/stretchr/testify v1.10.0
-	go.mongodb.org/mongo-driver v1.17.2
+	go.mongodb.org/mongo-driver/v2 v2.0.0
 	golang.org/x/sync v0.10.0
 	google.golang.org/grpc v1.69.4
 	google.golang.org/protobuf v1.36.2
@@ -91,6 +91,7 @@ require (
 	github.com/hashicorp/go-multierror v1.1.1
 	github.com/hashicorp/go-plugin v1.4.10
 	github.com/lesismal/nbio v1.5.12
+	go.mongodb.org/mongo-driver v1.17.2
 	google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422
 )
 
diff --git a/go.sum b/go.sum
index 7a355f78a..2fc1f0098 100644
--- a/go.sum
+++ b/go.sum
@@ -414,6 +414,7 @@ go.mongodb.org/mongo-driver v1.17.1 h1:Wic5cJIwJgSpBhe3lx3+/RybR5PiYRMpVFgO7cOHy
 go.mongodb.org/mongo-driver v1.17.1/go.mod h1:wwWm/+BuOddhcq3n68LKRmgk2wXzmF6s0SFOa0GINL4=
 go.mongodb.org/mongo-driver v1.17.2 h1:gvZyk8352qSfzyZ2UMWcpDpMSGEr1eqE4T793SqyhzM=
 go.mongodb.org/mongo-driver v1.17.2/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
+go.mongodb.org/mongo-driver/v2 v2.0.0/go.mod h1:nSjmNq4JUstE8IRZKTktLgMHM4F1fccL6HGX1yh+8RA=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
 go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
-- 
GitLab


From e44cc99e109850a1157f2b4816d63a1b089d2f80 Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@stud.h-da.de>
Date: Thu, 16 Jan 2025 01:00:04 +0100
Subject: [PATCH 45/79] (ui): implement UpdateIndicator

---
 .../devices/reducer/device.reducer.ts         | 15 ++++++
 .../devices/routines/device.routine.ts        | 12 ++++-
 .../components/devices/view/device.view.tsx   | 14 +++--
 .../devices/view_model/device.viewmodel.ts    |  2 +-
 .../src/i18n/locales/en/translations.json     |  3 ++
 .../update-indicator.layout.tsx               | 52 +++++++++++++++++++
 .../update-indicator.viewmodel.tsx            | 39 ++++++++++++++
 .../src/shared/reducer/routine.reducer.ts     | 10 +++-
 react-ui/src/shared/style/colors.scss         |  2 +-
 react-ui/src/shared/types/thunk.type.ts       |  3 +-
 10 files changed, 142 insertions(+), 10 deletions(-)
 create mode 100644 react-ui/src/shared/layouts/grid.layout/update-inidicator.layout/update-indicator.layout.tsx
 create mode 100644 react-ui/src/shared/layouts/grid.layout/update-inidicator.layout/update-indicator.viewmodel.tsx

diff --git a/react-ui/src/components/devices/reducer/device.reducer.ts b/react-ui/src/components/devices/reducer/device.reducer.ts
index cea12fbc9..f211fe024 100755
--- a/react-ui/src/components/devices/reducer/device.reducer.ts
+++ b/react-ui/src/components/devices/reducer/device.reducer.ts
@@ -5,6 +5,8 @@ import {
 } from '@api/api'
 import { DeviceViewTabValues } from '@component/devices/view/device.view.tabs'
 import { createSlice, PayloadAction } from '@reduxjs/toolkit'
+import { refreshUpdateTimer } from '@shared/reducer/routine.reducer'
+import { Category, CategoryType } from '@shared/types/category.type'
 import { REHYDRATE } from 'redux-persist'
 import { RootState } from 'src/stores'
 import '../routines/index'
@@ -129,6 +131,19 @@ startListening({
     },
 })
 
+startListening({
+    predicate: (action) => setSelectedMne.match(action),
+    effect: async (action, listenerApi) => {
+        listenerApi.dispatch(refreshUpdateTimer(Category.TAB as CategoryType))
+    },
+})
+
+startListening({
+    predicate: (action) => setDevices.match(action),
+    effect: async (action, listenerApi) => {
+        listenerApi.dispatch(refreshUpdateTimer(Category.DEVICE as CategoryType))
+    },
+})
 
 /**
  * On startup reset the selected device 
diff --git a/react-ui/src/components/devices/routines/device.routine.ts b/react-ui/src/components/devices/routines/device.routine.ts
index ef92b1c8e..058f65f9f 100755
--- a/react-ui/src/components/devices/routines/device.routine.ts
+++ b/react-ui/src/components/devices/routines/device.routine.ts
@@ -1,21 +1,29 @@
 import { NetworkElementServiceGetAllFlattenedApiArg, api } from '@api/api'
 import { setDevices } from '@component/devices/reducer/device.reducer'
 import { createAsyncThunk } from '@reduxjs/toolkit'
+import { addRoutine } from '@shared/reducer/routine.reducer'
 import { setUser } from '@shared/reducer/user.reducer'
+import { Category, CategoryType } from '@shared/types/category.type'
 import { RootState } from 'src/stores'
 import { startListening } from '../../../stores/middleware/listener.middleware'
 
 export const FETCH_DEVICE_ACTION = 'subscription/device/fetchDevices'
 
 // continously fetch devices
-const FETCH_DEVICES_INTERVAL = 15000 // in ms
 startListening({
     actionCreator: setUser,
     effect: async (_, listenerApi) => {
-        listenerApi.dispatch(fetchDevicesThunk())
+        listenerApi.dispatch(
+            addRoutine({
+                thunk: fetchDevicesThunk,
+                category: Category.DEVICE as CategoryType,
+                payload: {},
+            })
+        )
     },
 })
 
+const FETCH_DEVICES_INTERVAL = 15000 // in ms
 export const fetchDevicesThunk = createAsyncThunk(FETCH_DEVICE_ACTION, (_, thunkApi) => {
     const { user } = thunkApi.getState() as RootState
 
diff --git a/react-ui/src/components/devices/view/device.view.tsx b/react-ui/src/components/devices/view/device.view.tsx
index f705aa4eb..6bd702bf7 100755
--- a/react-ui/src/components/devices/view/device.view.tsx
+++ b/react-ui/src/components/devices/view/device.view.tsx
@@ -1,13 +1,15 @@
 import { faGripVertical } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { GridLayout } from '@layout/grid.layout/grid.layout';
+import UpdateIndicator from '@layout/grid.layout/update-inidicator.layout/update-indicator.layout';
+import { Category, CategoryType } from '@shared/types/category.type';
 import { useRef } from 'react';
 import { Button, Col, Container, Form, Nav, NavLink, Row } from 'react-bootstrap';
 import { useTranslation } from 'react-i18next';
 import { useDeviceViewModel } from '../view_model/device.viewmodel';
 import './device.scss';
 import { DeviceViewTable } from './device.view.table';
-import { DeviceViewTabs, DeviceViewTabValues } from './device.view.tabs';
+import { DeviceViewTabValues, DeviceViewTabs } from './device.view.tabs';
 
 const DeviceView = () => {
     const { t } = useTranslation('common');
@@ -20,13 +22,16 @@ const DeviceView = () => {
                 <>
                     <div key="device-list">
                         <Container className='c-box hoverable h-100'>
+                            <UpdateIndicator
+                                category={Category.DEVICE as CategoryType}
+                                updateInterval={15000}
+                            />
                             <FontAwesomeIcon icon={faGripVertical} className="drag-handle" />
                             <Row>
                                 <Col sm={12} className='mt-4'>
                                     <h3 className='text-black-50'>{t('device.title')}</h3>
                                 </Col>
                             </Row>
-
                             <Row className='align-items-center'>
                                 <Col xs={12} sm={6}>
                                     <Form.Group controlId='device.search' className='p-0 mx-1 pt-2'>
@@ -48,6 +53,10 @@ const DeviceView = () => {
 
                     <div key="device-details">
                         <Container className='c-box hoverable h-100'>
+                            <UpdateIndicator
+                                category={Category.TAB as CategoryType}
+                                updateInterval={5000}
+                            />
                             <FontAwesomeIcon icon={faGripVertical} className="drag-handle" />
                             <Row>
                                 <Col xs={12} className='mt-4'>
@@ -67,7 +76,6 @@ const DeviceView = () => {
                                     </Nav>
                                 </Col>
                             </Row>
-
                             <Row className='align-items-start'>
                                 <Col xs={12}>
                                     {DeviceViewTabs(activeTab)}
diff --git a/react-ui/src/components/devices/view_model/device.viewmodel.ts b/react-ui/src/components/devices/view_model/device.viewmodel.ts
index 9a0fbe17a..1cce2d59a 100755
--- a/react-ui/src/components/devices/view_model/device.viewmodel.ts
+++ b/react-ui/src/components/devices/view_model/device.viewmodel.ts
@@ -7,7 +7,7 @@ export const useDeviceViewModel = () => {
     const { activeTab } = useAppSelector((state) => state.device)
     const dispatch = useAppDispatch()
 
-    useEffect(() => {}, [])
+    useEffect(() => { }, [])
 
     const handleActiveTabLink = (tabLink: DeviceViewTabValues) => {
         return activeTab === tabLink ? 'active' : ''
diff --git a/react-ui/src/i18n/locales/en/translations.json b/react-ui/src/i18n/locales/en/translations.json
index fb3ca729c..53444b9e0 100755
--- a/react-ui/src/i18n/locales/en/translations.json
+++ b/react-ui/src/i18n/locales/en/translations.json
@@ -53,6 +53,9 @@
                 "yang_model": {
                     "title": "YANG Model"
                 }
+            },
+            "box": {
+                "lastUpdate": "Last updated {{seconds}} seconds ago"
             }
         },
         "protected": {
diff --git a/react-ui/src/shared/layouts/grid.layout/update-inidicator.layout/update-indicator.layout.tsx b/react-ui/src/shared/layouts/grid.layout/update-inidicator.layout/update-indicator.layout.tsx
new file mode 100644
index 000000000..d71bb6cce
--- /dev/null
+++ b/react-ui/src/shared/layouts/grid.layout/update-inidicator.layout/update-indicator.layout.tsx
@@ -0,0 +1,52 @@
+import { faCircle } from '@fortawesome/free-solid-svg-icons'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import React, { useState } from 'react'
+import { Overlay, Tooltip } from 'react-bootstrap'
+import { useTranslation } from 'react-i18next'
+import { CategoryType } from '../types'
+import { useUpdateIndicatorViewModel } from './update-indicator.viewmodel'
+
+interface UpdateIndicatorProps {
+    category: CategoryType
+    updateInterval: number
+}
+
+const UpdateIndicator: React.FC<UpdateIndicatorProps> = ({ category, updateInterval }) => {
+    const [showTooltip, setShowTooltip] = useState(false)
+    const { t } = useTranslation('common')
+    const target = React.useRef(null)
+    const { secondsSinceUpdate, getStatusColor } = useUpdateIndicatorViewModel(category)
+
+    return (
+        <div
+            className="position-absolute"
+            style={{
+                top: 0,
+                right: '40px',
+                padding: '10px',
+                zIndex: 10
+            }}
+        >
+            <div
+                ref={target}
+                onMouseEnter={() => setShowTooltip(true)}
+                onMouseLeave={() => setShowTooltip(false)}
+                style={{ cursor: 'pointer' }}
+            >
+                <FontAwesomeIcon
+                    icon={faCircle}
+                    className={getStatusColor(updateInterval)}
+                    size="sm"
+                />
+            </div>
+
+            <Overlay target={target.current} show={showTooltip} placement="bottom">
+                <Tooltip id="update-tooltip">
+                    {t('device.box.lastUpdate', { seconds: secondsSinceUpdate })}
+                </Tooltip>
+            </Overlay>
+        </div>
+    )
+}
+
+export default UpdateIndicator
\ No newline at end of file
diff --git a/react-ui/src/shared/layouts/grid.layout/update-inidicator.layout/update-indicator.viewmodel.tsx b/react-ui/src/shared/layouts/grid.layout/update-inidicator.layout/update-indicator.viewmodel.tsx
new file mode 100644
index 000000000..bb91b0b17
--- /dev/null
+++ b/react-ui/src/shared/layouts/grid.layout/update-inidicator.layout/update-indicator.viewmodel.tsx
@@ -0,0 +1,39 @@
+import { useAppSelector } from "@hooks"
+import { CategoryType } from "@shared/types/category.type"
+import { useEffect, useState } from 'react'
+
+export const useUpdateIndicatorViewModel = (category: CategoryType) => {
+    const { thunks } = useAppSelector((state) => state.routine)
+    const [secondsSinceUpdate, setSecondsSinceUpdate] = useState<number>(-1)
+
+    useEffect(() => {
+        const updateTimer = () => {
+            const lastupdate = thunks[category]?.lastupdate
+            if (lastupdate) {
+                setSecondsSinceUpdate(Math.round((Date.now() - lastupdate) / 1000))
+            } else {
+                setSecondsSinceUpdate(-1)
+            }
+        }
+
+        // Initial update
+        updateTimer()
+
+        // Set up interval for updates
+        const intervalId = setInterval(updateTimer, 1000)
+
+        return () => clearInterval(intervalId)
+    }, [category, thunks])
+
+    const getStatusColor = (updateInterval: number) => {
+        const updateIntervalSeconds = updateInterval / 1000
+        if (secondsSinceUpdate > updateIntervalSeconds * 0.9) return "text-primary"
+        if (secondsSinceUpdate > updateIntervalSeconds * 1.3) return "text-danger"
+        return "text-bg-primary"
+    }
+
+    return {
+        secondsSinceUpdate,
+        getStatusColor
+    }
+}
\ No newline at end of file
diff --git a/react-ui/src/shared/reducer/routine.reducer.ts b/react-ui/src/shared/reducer/routine.reducer.ts
index 5e9c3401a..95d5f06e7 100755
--- a/react-ui/src/shared/reducer/routine.reducer.ts
+++ b/react-ui/src/shared/reducer/routine.reducer.ts
@@ -16,6 +16,7 @@ const initialState: ReducerState = {
         TABLE: null,
         TAB: null
     },
+
 }
 
 
@@ -27,19 +28,24 @@ const RoutineSlice = createSlice({
             const thunk: ThunkPersist = {
                 category: payload.category,
                 payload: payload.payload,
-                thunkId: payload.thunk.id
+                thunkId: payload.thunk.id,
+                lastupdate: Date.now()
             }
 
             state.thunks[payload.category] = thunk
         },
 
+        refreshUpdateTimer: (state: any, { payload }: PayloadAction<CategoryType>) => {
+            state.thunks[payload].lastupdate = Date.now()
+        },
+
         removeAll: (state) => {
             state.thunks = initialState.thunks
         },
     },
 })
 
-export const { addRoutine } = RoutineSlice.actions
+export const { addRoutine, refreshUpdateTimer } = RoutineSlice.actions
 
 // on logout remove all routine
 startListening({
diff --git a/react-ui/src/shared/style/colors.scss b/react-ui/src/shared/style/colors.scss
index 29c971f86..4469a4a5b 100755
--- a/react-ui/src/shared/style/colors.scss
+++ b/react-ui/src/shared/style/colors.scss
@@ -2,7 +2,7 @@ $theme-colors: (
   "primary": #b350e0,
   "primary::hover": #ddaff3af,
   "bg-primary": #ededed,
-  "danger": #ffdcdc,
+  "danger": #ff0000,
   "warning": #dbd116,
   "dark": #595959,
   "black": #000000
diff --git a/react-ui/src/shared/types/thunk.type.ts b/react-ui/src/shared/types/thunk.type.ts
index 9143871f0..ff037d796 100644
--- a/react-ui/src/shared/types/thunk.type.ts
+++ b/react-ui/src/shared/types/thunk.type.ts
@@ -19,5 +19,6 @@ export interface ThunkDTO {
 export interface ThunkPersist {
     thunkId: number,
     payload: Object
-    category: CategoryType
+    category: CategoryType,
+    lastupdate: number
 }
-- 
GitLab


From 7f40202665d68ac7839aa1b5071b3d4f6db97485 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Thu, 16 Jan 2025 07:34:38 +0000
Subject: [PATCH 46/79] [renovate] Update
 google.golang.org/genproto/googleapis/api digest to 1a7da9e

See merge request danet/gosdn!1158

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 4 ++--
 go.sum | 4 ++++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/go.mod b/go.mod
index f48265086..5d7b488be 100644
--- a/go.mod
+++ b/go.mod
@@ -25,7 +25,7 @@ require (
 	go.mongodb.org/mongo-driver/v2 v2.0.0
 	golang.org/x/sync v0.10.0
 	google.golang.org/grpc v1.69.4
-	google.golang.org/protobuf v1.36.2
+	google.golang.org/protobuf v1.36.3
 	gopkg.in/yaml.v3 v3.0.1
 )
 
@@ -92,7 +92,7 @@ require (
 	github.com/hashicorp/go-plugin v1.4.10
 	github.com/lesismal/nbio v1.5.12
 	go.mongodb.org/mongo-driver v1.17.2
-	google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422
+	google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f
 )
 
 require (
diff --git a/go.sum b/go.sum
index 2fc1f0098..893cfcf40 100644
--- a/go.sum
+++ b/go.sum
@@ -618,6 +618,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d h1:
 google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d/go.mod h1:2v7Z7gP2ZUOGsaFyxATQSRoBnKygqVq2Cwnvom7QiqY=
 google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 h1:GVIKPyP/kLIyVOgOnTwFOrvQaQUzOzGMCxgFUOEmm24=
 google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422/go.mod h1:b6h1vNKhxaSoEI+5jc3PJUCustfli/mRab7295pY7rw=
+google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA=
+google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed h1:J6izYgfBXAI3xTKLgxzTmUltdYaLsuBxFCgDHWJ/eXg=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
@@ -690,6 +692,8 @@ google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/g
 google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 google.golang.org/protobuf v1.36.2 h1:R8FeyR1/eLmkutZOM5CWghmo5itiG9z0ktFlTVLuTmU=
 google.golang.org/protobuf v1.36.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=
+google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
-- 
GitLab


From a4bf8c5915429d5e0643e988f04cc18f131b3fb7 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Thu, 16 Jan 2025 07:47:44 +0000
Subject: [PATCH 47/79] [renovate] Update module
 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go to
 v1.36.3-20241127180247-a33202765966.1

See merge request danet/gosdn!1159

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 2 +-
 go.sum | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/go.mod b/go.mod
index 5d7b488be..2ea505681 100644
--- a/go.mod
+++ b/go.mod
@@ -86,7 +86,7 @@ require (
 )
 
 require (
-	buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.2-20241127180247-a33202765966.1
+	buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.3-20241127180247-a33202765966.1
 	github.com/bufbuild/protovalidate-go v0.8.2
 	github.com/hashicorp/go-multierror v1.1.1
 	github.com/hashicorp/go-plugin v1.4.10
diff --git a/go.sum b/go.sum
index 893cfcf40..3a04475e3 100644
--- a/go.sum
+++ b/go.sum
@@ -20,6 +20,8 @@ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.1-2024112718024
 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.1-20241127180247-a33202765966.1/go.mod h1:/zlFuuECgFgewxwW6qQKgvMJ07YZkWlVkcSxEhJprJw=
 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.2-20241127180247-a33202765966.1 h1:BICM6du/XzvEgeorNo4xgohK3nMTmEPViGyd5t7xVqk=
 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.2-20241127180247-a33202765966.1/go.mod h1:JnMVLi3qrNYPODVpEKG7UjHLl/d2zR221e66YCSmP2Q=
+buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.3-20241127180247-a33202765966.1 h1:cQZXKoQ+eB0kykzfJe80RP3nc+3PWbbBrUBm8XNYAQY=
+buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.3-20241127180247-a33202765966.1/go.mod h1:6VPKM8zbmgf9qsmkmKeH49a36Vtmidw3rG53B5mTenc=
 cel.dev/expr v0.18.0 h1:CJ6drgk+Hf96lkLikr4rFf19WrU0BOWEihyZnI2TAzo=
 cel.dev/expr v0.18.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-- 
GitLab


From 9187fcd736ca147fb887466268553b5917c6cc46 Mon Sep 17 00:00:00 2001
From: Fabian Seidl <fabian.seidl@h-da.de>
Date: Thu, 16 Jan 2025 08:02:50 +0000
Subject: [PATCH 48/79] Improve documentation in README

See merge request danet/gosdn!1148
---
 README.md | 57 ++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 35 insertions(+), 22 deletions(-)

diff --git a/README.md b/README.md
index e8e273c2e..a418a5ab7 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ You can find a detailed manual to install all necessary tools at our [Wiki](http
 There you can also find some tutorials to get to know the SDN controller:
 - [Lab00 education](https://code.fbi.h-da.de/danet/gosdn/-/wikis/Labs/Lab00-education), which is used in education
 - [Lab00](https://code.fbi.h-da.de/danet/gosdn/-/wikis/Labs/Lab00), which uses servers with gNMI targets instead of Arista switch images (needs less storage than Lab01)
-- [Lab01](https://code.fbi.h-da.de/danet/gosdn/-/wikis/Labs/Lab01), which uses servers with Arista switch images (needs less storage than Lab01)
+- [Lab01](https://code.fbi.h-da.de/danet/gosdn/-/wikis/Labs/Lab01), which uses servers with Arista switch images
 ---
 ## Table of Contents
 
@@ -72,6 +72,10 @@ A simple showcase how the controller can be addressed after
   on them. They are currently unsupported.
 - `controller` represents the `goSDN-controller`.
 
+---
+
+## Concepts
+
 <div align="center" style="margin-bottom:3em; margin-top:4em">
   <img src="documentation/figures/overview/updated_controller_architecture_overview.drawio.png" />
     <p> Overview of the controller architecture</p>
@@ -87,15 +91,27 @@ A simple showcase how the controller can be addressed after
   <p> Detailed view of plugin mechanism</p>
 </div>
 
----
-
-## Concepts
+### Nucleus
 
 The `goSDN` controllers core - also called `nucleus` - is a lightweight library
 that manages principal network domains and provides southbound interface
 operations for managed network elements.
 
-In addition, we provide a simple Northbound-API (gRPC) for the controller [right here](https://code.fbi.h-da.de/danet/gosdn/-/tree/master/controller/api).
+### Principal Networking Domain (PND)
+
+The PND is the single source of truth within a network. Its state is held and
+maintained by the controller. Any configuration of an MNE has to be applied by
+the PND.
+
+### Managed Network Element (MNE)
+
+Any network element directly configured by `goSDN`
+
+### Northbound Interface (NBI)
+
+The NBI is implemented using gRPC which means one can interact with the controller with any language that supports gRPC when using our own [proto definitions](https://code.fbi.h-da.de/danet/gosdn/-/tree/master/api/proto/gosdn).
+
+In addition, we provide a simple abstraction layer of the Northbound-API to use with the controller in Go [right here](https://code.fbi.h-da.de/danet/gosdn/-/tree/master/controller/api).
 
 To use the API, you can build a login method as is done in the `inventory-manager` in `utils.go`.
 You log in, create a session context with the returned token, then you can simply make API calls with this context.
@@ -120,7 +136,7 @@ func createContextWithAuthorization(sessionToken string) context.Context {
 }
 ```
 
-The code in your app:
+An example on how the code in your app to register a MNE in the controller could look like:
 ```golang
 import "code.fbi.h-da.de/danet/gosdn/controller/api"
 
@@ -130,20 +146,11 @@ ctx := createContextWithAuthorization(sessionToken)
 _, err := api.AddNetworkElement(i.sessionContext, i.controllerAddress, networkElement.Name, networkElement.UUID, &transportOptions, pluginUUID, pndUUID, []string{})
 ```
 
+The gRPC services can also be reached using HTTP requests via the gRPC-Gateway. The fitting OpenAPI definitions can be found [here](https://code.fbi.h-da.de/danet/gosdn/-/tree/master/api/openapiv2?ref_type=heads).
 
-The gRPC services can also be reached using HTTP requests via the gRPC-Gateway. The fitting OpenAPI definitions can be found [here](https://code.fbi.h-da.de/danet/gosdn/-/tree/master/api/openapiv2?ref_type=heads). Note, that this is experimental and tested less well. If you want to use the controller in secure mode which implies it's mandatory to login and provide the received token in other requests via the HTTP header with the key-value pair:
+Note, that this is experimental and tested less well. If you want to use the controller in secure mode it is mandatory to login and provide the received token in other requests via the HTTP header with the key-value pair:
 `"authorize: token"`.
 
-### Principal Networking Domain (PND)
-
-The PND is the single source of truth within a network. Its state is held and
-maintained by the controller. Any configuration of an MNE has to be applied by
-the PND.
-
-### Managed Network Element (MNE)
-
-Any network element directly configured by `goSDN`
-
 ---
 ## Launch goSDN Controller local
 In this chapter, you learn how to launch the goSDN controller.
@@ -152,11 +159,9 @@ Firstly, make sure that you're located in the root directory of goSDN.
 `goSDN` provides a `Makefile` for all common use cases.
 
 ```sh
-# build the application files for goSDN, cSBI orchestrator, gosdnc (CLI).
-make build
+# build the application files for goSDN, cSBI orchestrator (currently not in use), gosdnc (CLI).
 
-# build the Dockerfiles for goSDN, cSBI orchestrator, gosdnc (CLI).
-make containerize-all
+make build
 ```
 
 Depending on how you want to use the controller, you might need to edit the example config files and provide the path to this or a new config file.
@@ -175,12 +180,20 @@ running `./gosdn` from the shell:
 
 ---
 
-## Getting Started
+## Getting Started using containers
 
 If you want to use the [playground](#playground) you have to make sure you
 have [containerlab](https://containerlab.dev/install/) installed on your
 system.
 
+It is possible to build all the docker containers using the following command from the root directory of the project:
+```sh
+# build the Docker containers for goSDN, cSBI orchestrator (currently not in use), gosdnc (CLI) as well as some of the provided example applications.
+make containerize-all
+```
+
+Note that this command is included as a step when using any of the following enviroments like the playgrounds, labs etc. and therefore can be skipped.
+
 ### Playground
 
 With the help of [containerlab](https://containerlab.dev/) we provide simple test environments to play around with.
-- 
GitLab


From 43fb742ca1bb3dbe15e93176bc42a09c3e0acbc8 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Fri, 17 Jan 2025 08:09:19 +0000
Subject: [PATCH 49/79] [renovate] Update renovate/renovate Docker tag to
 v39.113.0

See merge request danet/gosdn!1169

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 .gitlab/ci/.renovate.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab/ci/.renovate.yml b/.gitlab/ci/.renovate.yml
index 81070e9da..afdfa6561 100644
--- a/.gitlab/ci/.renovate.yml
+++ b/.gitlab/ci/.renovate.yml
@@ -1,7 +1,7 @@
 renovate:
     stage: tools
 
-    image: renovate/renovate:39.107.0
+    image: renovate/renovate:39.113.0
 
     variables:
         LOG_LEVEL: debug
-- 
GitLab


From 4f75b82b42f3307687f1611497c8419f5b8dfe1a Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Mon, 20 Jan 2025 08:04:55 +0000
Subject: [PATCH 50/79] [renovate] Update renovate/renovate Docker tag to
 v39.117.2

See merge request danet/gosdn!1171

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 .gitlab/ci/.renovate.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab/ci/.renovate.yml b/.gitlab/ci/.renovate.yml
index afdfa6561..423d5c2b9 100644
--- a/.gitlab/ci/.renovate.yml
+++ b/.gitlab/ci/.renovate.yml
@@ -1,7 +1,7 @@
 renovate:
     stage: tools
 
-    image: renovate/renovate:39.113.0
+    image: renovate/renovate:39.117.2
 
     variables:
         LOG_LEVEL: debug
-- 
GitLab


From de6c7d6def16742990ace3bc12c16597371c7f4b Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Mon, 20 Jan 2025 08:15:47 +0000
Subject: [PATCH 51/79] [renovate] Update module github.com/lesismal/nbio to
 v1.6.0

See merge request danet/gosdn!1172

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 4 ++--
 go.sum | 4 ++++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/go.mod b/go.mod
index 2ea505681..37a31d82d 100644
--- a/go.mod
+++ b/go.mod
@@ -90,7 +90,7 @@ require (
 	github.com/bufbuild/protovalidate-go v0.8.2
 	github.com/hashicorp/go-multierror v1.1.1
 	github.com/hashicorp/go-plugin v1.4.10
-	github.com/lesismal/nbio v1.5.12
+	github.com/lesismal/nbio v1.6.0
 	go.mongodb.org/mongo-driver v1.17.2
 	google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f
 )
@@ -108,7 +108,7 @@ require (
 	github.com/hashicorp/errwrap v1.1.0 // indirect
 	github.com/hashicorp/go-hclog v1.5.0 // indirect
 	github.com/hashicorp/yamux v0.1.1 // indirect
-	github.com/lesismal/llib v1.1.13 // indirect
+	github.com/lesismal/llib v1.2.0 // indirect
 	github.com/lithammer/fuzzysearch v1.1.8 // indirect
 	github.com/mitchellh/go-testing-interface v1.14.1 // indirect
 	github.com/moby/patternmatcher v0.5.0 // indirect
diff --git a/go.sum b/go.sum
index 3a04475e3..59c538b85 100644
--- a/go.sum
+++ b/go.sum
@@ -226,12 +226,16 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0
 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
 github.com/lesismal/llib v1.1.13 h1:+w1+t0PykXpj2dXQck0+p6vdC9/mnbEXHgUy/HXDGfE=
 github.com/lesismal/llib v1.1.13/go.mod h1:70tFXXe7P1FZ02AU9l8LgSOK7d7sRrpnkUr3rd3gKSg=
+github.com/lesismal/llib v1.2.0 h1:76mtWL87Y2XTYSoBXNFMBmUZY6igHbQZW48c0gx32Hc=
+github.com/lesismal/llib v1.2.0/go.mod h1:70tFXXe7P1FZ02AU9l8LgSOK7d7sRrpnkUr3rd3gKSg=
 github.com/lesismal/nbio v1.5.10 h1:k9O6a2bG+eBJn4ed94d918AB55QxF0KEj0OHKLCppJQ=
 github.com/lesismal/nbio v1.5.10/go.mod h1:QsxE0fKFe1PioyjuHVDn2y8ktYK7xv9MFbpkoRFj8vI=
 github.com/lesismal/nbio v1.5.11 h1:MVjrzcej4NSJQMRT+S0dPZvVaiFUHD1JWnvr+FHIHOo=
 github.com/lesismal/nbio v1.5.11/go.mod h1:QsxE0fKFe1PioyjuHVDn2y8ktYK7xv9MFbpkoRFj8vI=
 github.com/lesismal/nbio v1.5.12 h1:YcUjjmOvmKEANs6Oo175JogXvHy8CuE7i6ccjM2/tv4=
 github.com/lesismal/nbio v1.5.12/go.mod h1:QsxE0fKFe1PioyjuHVDn2y8ktYK7xv9MFbpkoRFj8vI=
+github.com/lesismal/nbio v1.6.0 h1:QqkFifnJjcUOzMT8edybXiBa1qlvueYEszy4ZCVroDM=
+github.com/lesismal/nbio v1.6.0/go.mod h1:Ah601gkk8O67QG8uAEz6qP6JHZY4oG0FdWllj3R2Ouc=
 github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4=
 github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4=
 github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
-- 
GitLab


From 4676153deafc4f03f250a77822a6dee1b49540a6 Mon Sep 17 00:00:00 2001
From: Fabian Seidl <fabian.seidl@h-da.de>
Date: Mon, 20 Jan 2025 08:37:54 +0000
Subject: [PATCH 52/79] Resolve "Fix permissions on folders"

See merge request danet/gosdn!1168
---
 controller/cmd/root.go    | 2 +-
 controller/store/utils.go | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/controller/cmd/root.go b/controller/cmd/root.go
index c2dd7fb6c..4b52eb4a4 100644
--- a/controller/cmd/root.go
+++ b/controller/cmd/root.go
@@ -154,7 +154,7 @@ func initConfig() {
 func ensureFileSystemPathExists(pathToFile string) error {
 	emptyString := []byte("")
 	// create folder if it does not exist
-	if err := os.MkdirAll(configHome, 0600); err != nil {
+	if err := os.MkdirAll(configHome, 0700); err != nil {
 		return err
 	}
 	// create file if it does not exist
diff --git a/controller/store/utils.go b/controller/store/utils.go
index 9d8ebc838..d29dcf421 100644
--- a/controller/store/utils.go
+++ b/controller/store/utils.go
@@ -58,7 +58,7 @@ func ensureFileSystemStoreExists(pathToStore string) error {
 func ensureDirExists(fileName string) error {
 	dirName := filepath.Dir(fileName)
 	if _, serr := os.Stat(dirName); serr != nil {
-		merr := os.MkdirAll(dirName, 0600)
+		merr := os.MkdirAll(dirName, 0700)
 		if merr != nil {
 			return merr
 		}
-- 
GitLab


From c73d356601a19dc2f4885b224a448a506fd29ff6 Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@stud.h-da.de>
Date: Mon, 20 Jan 2025 10:22:43 +0100
Subject: [PATCH 53/79] Merge branch 'master' into ui-implement-metadata-screen

---
 .cobra.yaml                                   |   0
 .devcontainer/Dockerfile                      |   0
 .devcontainer/devcontainer.json               |   0
 .dockerignore                                 |   0
 .editorconfig                                 |   0
 .gitignore                                    |   0
 .gitlab-ci.yml                                |   0
 .gitlab/ci/.build-binaries.yml                |   0
 .gitlab/ci/.build-container-images.yml        |   0
 .gitlab/ci/.code-quality-ci.yml               |   0
 .gitlab/ci/.mk-docs-deploy.yml                |   0
 .gitlab/ci/.react-ui.yml                      |   3 +
 .gitlab/ci/.release-container.yml             |   0
 .gitlab/ci/.renovate.yml                      |   0
 .gitlab/ci/.security-and-compliance-ci.yml    |   0
 .gitlab/ci/.test.yml                          |   0
 .gitlab/ci/gnmi-cert-integration.Dockerfile   |   0
 .gitlab/ci/gosdn-integration.Dockerfile       |   0
 .gitlab/ci/legacy/.test.yml                   |   0
 .gitlab/issue_templates/Change Request.md     |   0
 .gitlab/issue_templates/Feature Proposal.md   |   0
 .gitlab/issue_templates/Issue Template.md     |   0
 .gitlab/merge_request_templates/Default.md    |   0
 .gitmodules                                   |   0
 .golangci.yml                                 |   0
 LICENSE                                       |   0
 Makefile                                      |   0
 README.md                                     |   0
 api/LICENSE                                   |   0
 api/Makefile                                  |   0
 api/README.md                                 |   0
 api/buf.gen.yaml                              |   0
 api/buf.work.yaml                             |   0
 api/cmd/gogen.go                              |   0
 api/deps/buf.yaml                             |   0
 .../.github/workflows/ci-cpp-build-gnmi.yml   |   0
 .../github.com/openconfig/gnmi/BUILD.bazel    |   0
 .../openconfig/gnmi/CONTRIBUTING.md           |   0
 api/deps/github.com/openconfig/gnmi/LICENSE   |   0
 api/deps/github.com/openconfig/gnmi/README.md |   0
 .../openconfig/gnmi/WORKSPACE.bazel           |   0
 .../github.com/openconfig/gnmi/cache/cache.go |   0
 .../openconfig/gnmi/cache/cache_test.go       |   0
 .../github.com/openconfig/gnmi/cli/cli.go     |   0
 .../openconfig/gnmi/cli/cli_test.go           |   0
 .../openconfig/gnmi/client/cache.go           |   0
 .../openconfig/gnmi/client/cache_test.go      |   0
 .../openconfig/gnmi/client/client.go          |   0
 .../openconfig/gnmi/client/client_test.go     |   0
 .../openconfig/gnmi/client/fake/fake.go       |   0
 .../openconfig/gnmi/client/fake/fake_test.go  |   0
 .../gnmi/client/flags/flags_test.go           |   0
 .../openconfig/gnmi/client/flags/intmap.go    |   0
 .../gnmi/client/flags/stringlist.go           |   0
 .../openconfig/gnmi/client/flags/stringmap.go |   0
 .../openconfig/gnmi/client/gnmi/client.go     |   0
 .../gnmi/client/gnmi/client_test.go           |   0
 .../gnmi/client/gnmi/credentials.go           |   0
 .../openconfig/gnmi/client/grpcutil/lookup.go |   0
 .../gnmi/client/grpcutil/lookup_test.go       |   0
 .../openconfig/gnmi/client/notification.go    |   0
 .../openconfig/gnmi/client/query.go           |   0
 .../openconfig/gnmi/client/reconnect.go       |   0
 .../openconfig/gnmi/client/reconnect_test.go  |   0
 .../openconfig/gnmi/client/register.go        |   0
 .../openconfig/gnmi/client/values.go          |   0
 .../openconfig/gnmi/cmd/gnmi_cli/gnmi_cli.go  |   0
 .../gnmi/cmd/gnmi_cli/gnmi_cli_test.go        |   0
 .../gnmi/cmd/gnmi_collector/docker/Dockerfile |   0
 .../gnmi/cmd/gnmi_collector/docker/README.md  |   0
 .../cmd/gnmi_collector/docker/config/cert.pem |   0
 .../gnmi_collector/docker/config/example.cfg  |   0
 .../cmd/gnmi_collector/docker/config/key.pem  |   0
 .../gnmi_collector/docker/supervisord.conf    |   0
 .../gnmi/cmd/gnmi_collector/gnmi_collector.go |   0
 .../cmd/gnmi_collector/gnmi_collector_test.go |   0
 .../gnmi/cmd/gnmi_collector/testdata/bad.cfg  |   0
 .../gnmi/cmd/gnmi_collector/testdata/bad.crt  |   0
 .../gnmi/cmd/gnmi_collector/testdata/bad.key  |   0
 .../gnmi/cmd/gnmi_collector/testdata/good.cfg |   0
 .../gnmi/cmd/gnmi_collector/testdata/good.crt |   0
 .../gnmi/cmd/gnmi_collector/testdata/good.key |   0
 .../gnmi_collector/testdata/unparseable.cfg   |   0
 .../openconfig/gnmi/coalesce/coalesce.go      |   0
 .../openconfig/gnmi/coalesce/coalesce_test.go |   0
 .../openconfig/gnmi/collector/collector.go    |   0
 .../gnmi/collector/collector_test.go          |   0
 .../openconfig/gnmi/connection/connection.go  |   0
 .../gnmi/connection/connection_test.go        |   0
 .../github.com/openconfig/gnmi/ctree/tree.go  |   0
 .../openconfig/gnmi/ctree/tree_test.go        |   0
 .../openconfig/gnmi/errdiff/errdiff.go        |   0
 .../openconfig/gnmi/errdiff/errdiff_test.go   |   0
 .../openconfig/gnmi/errlist/errlist.go        |   0
 .../openconfig/gnmi/errlist/errlist_test.go   |   0
 .../github.com/openconfig/gnmi/gnmi_deps.bzl  |   0
 api/deps/github.com/openconfig/gnmi/go.mod    |   0
 api/deps/github.com/openconfig/gnmi/go.sum    |   0
 .../openconfig/gnmi/latency/latency.go        |   0
 .../openconfig/gnmi/latency/latency_test.go   |   0
 .../openconfig/gnmi/manager/manager.go        |   0
 .../openconfig/gnmi/manager/manager_test.go   |   0
 .../openconfig/gnmi/manager/meta.go           |   0
 .../openconfig/gnmi/manager/meta_test.go      |   0
 .../github.com/openconfig/gnmi/match/match.go |   0
 .../openconfig/gnmi/match/match_test.go       |   0
 .../openconfig/gnmi/metadata/metadata.go      |   0
 .../openconfig/gnmi/metadata/metadata_test.go |   0
 .../yang/gnmi-collector-metadata.yang         |   0
 .../github.com/openconfig/gnmi/path/path.go   |   0
 .../openconfig/gnmi/path/path_test.go         |   0
 .../gnmi/proto/collector/BUILD.bazel          |   0
 .../gnmi/proto/collector/collector.pb.go      |   0
 .../gnmi/proto/collector/collector.proto      |   0
 .../gnmi/proto/collector/collector_grpc.pb.go |   0
 .../gnmi/proto/collector/collector_pb2.py     |   0
 .../proto/collector/collector_pb2_grpc.py     |   0
 .../openconfig/gnmi/proto/gnmi/BUILD.bazel    |   0
 .../openconfig/gnmi/proto/gnmi/gnmi.pb.go     |   0
 .../openconfig/gnmi/proto/gnmi/gnmi.proto     |   0
 .../gnmi/proto/gnmi/gnmi_grpc.pb.go           |   0
 .../openconfig/gnmi/proto/gnmi/gnmi_pb2.py    |   0
 .../gnmi/proto/gnmi/gnmi_pb2_grpc.py          |   0
 .../gnmi/proto/gnmi_ext/BUILD.bazel           |   0
 .../gnmi/proto/gnmi_ext/gnmi_ext.pb.go        |   0
 .../gnmi/proto/gnmi_ext/gnmi_ext.proto        |   0
 .../gnmi/proto/gnmi_ext/gnmi_ext_pb2.py       |   0
 .../gnmi/proto/gnmi_ext/gnmi_ext_pb2_grpc.py  |   0
 .../openconfig/gnmi/proto/target/BUILD.bazel  |   0
 .../openconfig/gnmi/proto/target/target.pb.go |   0
 .../openconfig/gnmi/proto/target/target.proto |   0
 .../gnmi/proto/target/target_pb2.py           |   0
 .../gnmi/proto/target/target_pb2_grpc.py      |   0
 .../openconfig/gnmi/subscribe/subscribe.go    |   0
 .../gnmi/subscribe/subscribe_test.go          |   0
 .../openconfig/gnmi/target/target.go          |   0
 .../openconfig/gnmi/target/target_test.go     |   0
 .../gnmi/testing/fake/gnmi/agent.go           |   0
 .../gnmi/testing/fake/gnmi/client.go          |   0
 .../fake/gnmi/cmd/fake_server/README.md       |   0
 .../fake/gnmi/cmd/fake_server/config.pb.txt   |   0
 .../fake/gnmi/cmd/fake_server/server.go       |   0
 .../gnmi/cmd/gen_fake_config/gen_config.go    |   0
 .../gnmi/testing/fake/gnmi/gnmi_test.go       |   0
 .../gnmi/testing/fake/proto/fake.pb.go        |   0
 .../gnmi/testing/fake/proto/fake.proto        |   0
 .../gnmi/testing/fake/proto/fake_grpc.pb.go   |   0
 .../gnmi/testing/fake/proto/fake_pb2.py       |   0
 .../gnmi/testing/fake/proto/fake_pb2_grpc.py  |   0
 .../gnmi/testing/fake/queue/fixed_queue.go    |   0
 .../gnmi/testing/fake/queue/queue.go          |   0
 .../gnmi/testing/fake/queue/queue_test.go     |   0
 .../fake/testing/grpc/config/config_test.go   |   0
 .../fake/testing/grpc/config/server_option.go |   0
 .../gnmi/testing/fake/testing/tls/tls.go      |   0
 .../gnmi/testing/fake/testing/tls/tls_test.go |   0
 .../github.com/openconfig/gnmi/value/value.go |   0
 .../openconfig/gnmi/value/value_test.go       |   0
 .../github.com/openconfig/gnmi/watch/watch.go |   0
 .../gnmi/proto/collector/collector.pb.go      |   0
 .../gnmi/proto/collector/collector_grpc.pb.go |   0
 .../openconfig/gnmi/proto/gnmi/gnmi.pb.go     |   0
 .../gnmi/proto/gnmi/gnmi_grpc.pb.go           |   0
 .../gnmi/proto/gnmi_ext/gnmi_ext.pb.go        |   0
 .../openconfig/gnmi/proto/target/target.pb.go |   0
 .../gnmi/testing/fake/proto/fake.pb.go        |   0
 .../gnmi/testing/fake/proto/fake_grpc.pb.go   |   0
 api/go/gosdn/app/app.pb.go                    |   0
 api/go/gosdn/app/app.pb.gw.go                 |   0
 api/go/gosdn/app/app_grpc.pb.go               |   0
 .../configurationmanagement.pb.go             |   0
 .../configurationmanagement.pb.gw.go          |   0
 .../configurationmanagement_grpc.pb.go        |   0
 api/go/gosdn/conflict/conflict.pb.go          |   0
 api/go/gosdn/csbi/csbi.pb.go                  |   0
 api/go/gosdn/csbi/csbi_grpc.pb.go             |   0
 .../gosdn/networkelement/networkelement.pb.go |   0
 .../networkelement/networkelement.pb.gw.go    |   0
 .../networkelement/networkelement_grpc.pb.go  |   0
 .../plugin-internal/plugin-internal.pb.go     |   0
 .../plugin-internal_grpc.pb.go                |   0
 .../plugin-registry/plugin-registry.pb.go     |   0
 .../plugin-registry_grpc.pb.go                |   0
 api/go/gosdn/plugin/plugin.pb.go              |   0
 api/go/gosdn/plugin/plugin_grpc.pb.go         |   0
 api/go/gosdn/pnd/pnd.pb.go                    |   0
 api/go/gosdn/pnd/pnd.pb.gw.go                 |   0
 api/go/gosdn/pnd/pnd_grpc.pb.go               |   0
 api/go/gosdn/rbac/rbac.pb.go                  |   0
 api/go/gosdn/rbac/rbac.pb.gw.go               |   0
 api/go/gosdn/rbac/rbac_grpc.pb.go             |   0
 api/go/gosdn/rbac/role.pb.go                  |   0
 api/go/gosdn/rbac/role.pb.gw.go               |   0
 api/go/gosdn/rbac/role_grpc.pb.go             |   0
 api/go/gosdn/rbac/user.pb.go                  |   0
 api/go/gosdn/rbac/user.pb.gw.go               |   0
 api/go/gosdn/rbac/user_grpc.pb.go             |   0
 api/go/gosdn/southbound/southbound.pb.go      |   0
 api/go/gosdn/southbound/southbound_grpc.pb.go |   0
 .../subscriptionmanagement.pb.go              |   0
 .../subscriptionmanagement.pb.gw.go           |   0
 .../subscriptionmanagement_grpc.pb.go         |   0
 api/go/gosdn/topology/link.pb.go              |   0
 api/go/gosdn/topology/node.pb.go              |   0
 api/go/gosdn/topology/port.pb.go              |   0
 api/go/gosdn/topology/route.pb.go             |   0
 api/go/gosdn/topology/routingTable.pb.go      |   0
 api/go/gosdn/topology/routingTable.pb.gw.go   |   0
 api/go/gosdn/topology/routingTable_grpc.pb.go |   0
 api/go/gosdn/topology/topology.pb.go          |   0
 api/go/gosdn/topology/topology.pb.gw.go       |   0
 api/go/gosdn/topology/topology_grpc.pb.go     |   0
 api/go/gosdn/transport/transport.pb.go        |   0
 api/openapiv2/gosdn_northbound.swagger.json   |   0
 api/proto/buf.lock                            |   0
 api/proto/buf.yaml                            |   0
 api/proto/gosdn/app/app.proto                 |   0
 .../configurationmanagement.proto             |   0
 api/proto/gosdn/conflict/conflict.proto       |   0
 api/proto/gosdn/csbi/csbi.proto               |   0
 .../gosdn/networkelement/networkelement.proto |   0
 .../plugin-internal/plugin-internal.proto     |   0
 .../plugin-registry/plugin-registry.proto     |   0
 api/proto/gosdn/plugin/plugin.proto           |   0
 api/proto/gosdn/pnd/pnd.proto                 |   0
 api/proto/gosdn/rbac/rbac.proto               |   0
 api/proto/gosdn/rbac/role.proto               |   0
 api/proto/gosdn/rbac/user.proto               |   0
 api/proto/gosdn/southbound/southbound.proto   |   0
 .../subscriptionmanagement.proto              |   0
 api/proto/gosdn/topology/link.proto           |   0
 api/proto/gosdn/topology/node.proto           |   0
 api/proto/gosdn/topology/port.proto           |   0
 api/proto/gosdn/topology/route.proto          |   0
 api/proto/gosdn/topology/routingTable.proto   |   0
 api/proto/gosdn/topology/topology.proto       |   0
 api/proto/gosdn/transport/transport.proto     |   0
 api/third_party/validator/validator.proto     |   0
 application-framework/event/event.go          |   0
 application-framework/event/eventService.go   |   0
 application-framework/event/event_test.go     |   0
 application-framework/event/topics.go         |   0
 application-framework/event/type.go           |   0
 .../models/model-handling.go                  |   0
 .../models/model-handling_test.go             |   0
 .../registration/registration.go              |   0
 applications/arista-routing-engine/app.go     |   0
 .../arista-routing-engine.Dockerfile          |   0
 ...sta-routing-engine.Dockerfile.dockerignore |   0
 applications/arista-routing-engine/main.go    |   0
 .../arista-routing-engine/network-element.go  |   0
 applications/arista-routing-engine/routing.go |   0
 .../basic-interface-monitoring/app.go         |   0
 .../basic-interface-monitoring/http.go        |   0
 .../basic-interface-monitoring/main.go        |   0
 .../network-element.go                        |   0
 .../webpage/index.html                        |   0
 applications/hostname-checker/app.go          |   0
 applications/hostname-checker/device.go       |   0
 applications/hostname-checker/main.go         |   0
 applications/inventory-manager/README.md      |   0
 .../inventory-manager/config/config.go        |   0
 applications/inventory-manager/example.yml    |   0
 .../inventory-manager.Dockerfile              |   0
 .../inventory-manager.Dockerfile.dockerignore |   0
 .../inventoryManager/inventoryManager.go      |   0
 .../inventoryManager/util.go                  |   0
 applications/inventory-manager/main.go        |   0
 applications/venv-manager/Readme.md           |   0
 .../venv-manager/containerlab/containerlab.go |   0
 applications/venv-manager/links/link.go       |   0
 applications/venv-manager/main.go             |   0
 applications/venv-manager/node/node.go        |   0
 applications/venv-manager/port/port.go        |   0
 .../venv-manager/topology/topology.go         |   0
 .../venv-manager/venv-manager.Dockerfile      |   0
 .../venv-manager.Dockerfile.dockerignore      |   0
 .../venv-manager/venv-manager/venv-manager.go |   0
 .../venv-manager/yang-parser/yang-parser.go   |   0
 applications/ws-events/app.go                 |   0
 applications/ws-events/main.go                |   0
 applications/ws-events/ws-events.Dockerfile   |   0
 .../ws-events.Dockerfile.dockerignore         |   0
 applications/ws-events/ws.go                  |   0
 cli/LICENSE                                   |   0
 cli/README.md                                 |   0
 cli/adapter/PndAdapter.go                     |   0
 cli/adapter/PndAdapter_test.go                |   0
 cli/build/ci/.security-and-compliance-ci.yml  |   0
 cli/build/ci/.test.yml                        |   0
 cli/cli.Dockerfile                            |   0
 cli/cli.Dockerfile.dockerignore               |   0
 cli/cmd/change.go                             |   0
 cli/cmd/changeCommit.go                       |   0
 cli/cmd/changeConfirm.go                      |   0
 cli/cmd/changeGet.go                          |   0
 cli/cmd/changeList.go                         |   0
 cli/cmd/config/.gosdnc.toml                   |   0
 cli/cmd/list.go                               |   0
 cli/cmd/login.go                              |   0
 cli/cmd/logout.go                             |   0
 cli/cmd/networkElement.go                     |   0
 cli/cmd/networkElementCreate.go               |   0
 cli/cmd/networkElementList.go                 |   0
 cli/cmd/networkElementPath.go                 |   0
 cli/cmd/networkElementPathDelete.go           |   0
 cli/cmd/networkElementPathGet.go              |   0
 cli/cmd/networkElementPathGetIntended.go      |   0
 cli/cmd/networkElementPathSet.go              |   0
 cli/cmd/networkElementRemove.go               |   0
 cli/cmd/networkElementShow.go                 |   0
 cli/cmd/networkElementSubscribe.go            |   0
 cli/cmd/plugin.go                             |   0
 cli/cmd/pluginList.go                         |   0
 cli/cmd/pnd.go                                |   0
 cli/cmd/pndCreate.go                          |   0
 cli/cmd/pndGet.go                             |   0
 cli/cmd/pndList.go                            |   0
 cli/cmd/pndRemove.go                          |   0
 cli/cmd/pndUse.go                             |   0
 cli/cmd/prompt.go                             |   0
 cli/cmd/role.go                               |   0
 cli/cmd/roleCreate.go                         |   0
 cli/cmd/roleGetAll.go                         |   0
 cli/cmd/root.go                               |   0
 cli/cmd/subManagement.go                      |   0
 cli/cmd/subManagementGetAll.go                |   0
 cli/cmd/subManagementResetAll.go              |   0
 cli/cmd/user.go                               |   0
 cli/cmd/userCreate.go                         |   0
 cli/cmd/userDelete.go                         |   0
 cli/cmd/userGet.go                            |   0
 cli/cmd/userGetAll.go                         |   0
 cli/cmd/userUpdate.go                         |   0
 cli/cmd/utils.go                              |   0
 cli/cmd/utils_test.go                         |   0
 cli/completer/utils.go                        |   0
 cli/completer/yangSchemaCompleter.go          |   0
 cli/config/.cobra.yaml                        |   0
 cli/config/gosdnc.toml.example                |   0
 cli/main.go                                   |   0
 .../integrationtest.clab.tmpl.yml             |   0
 .../integrationtest_branch.clab.tmpl.yml      |   0
 config.js                                     |   0
 controller/ARCHITECTURE.md                    |   0
 controller/CONTRIBUTING.md                    |   0
 controller/Dockerfile.debug                   |   0
 controller/Makefile                           |   0
 controller/README.md                          |   0
 controller/api/apiUtil_test.go                |   0
 controller/api/api_test.go                    |   0
 controller/api/api_test.toml                  |   0
 controller/api/app.go                         |   0
 controller/api/auth.go                        |   0
 controller/api/auth_test.go                   |   0
 controller/api/change.go                      |   0
 controller/api/configurationManagement.go     |   0
 controller/api/grpc.go                        |   0
 controller/api/initialise_test.go             |   0
 controller/api/managedNetworkElement.go       |   0
 controller/api/plugin.go                      |   0
 controller/api/pnd.go                         |   0
 controller/api/role.go                        |   0
 controller/api/role_test.go                   |   0
 controller/api/subManagement.go               |   0
 controller/api/user.go                        |   0
 controller/api/user_test.go                   |   0
 controller/app/DatabaseStore.go               |   0
 controller/app/Service.go                     |   0
 controller/app/app.go                         |   0
 controller/app/store.go                       |   0
 controller/app/utils.go                       |   0
 controller/cmd/gosdn/main.go                  |   0
 controller/cmd/root.go                        |   0
 controller/cmd/version.go                     |   0
 controller/config/config.go                   |   0
 controller/config/config_test.go              |   0
 controller/config/environment.go              |   0
 controller/config/gnmiSubscriptionConfig.go   |   0
 controller/configs/.gitkeep                   |   0
 controller/configs/basic-docker-compose.toml  |   0
 .../configs/containerlab-gosdn.toml.example   |   0
 .../configs/development-gosdn.toml.example    |   0
 .../configs/gNMISubscriptions.txt.example     |   0
 .../configs/integration-test-gosdn.toml       |   0
 controller/conflict/versioning.go             |   0
 controller/controller.Dockerfile              |   0
 controller/controller.Dockerfile.dockerignore |   0
 controller/controller.go                      |   0
 controller/controller_test.go                 |   0
 controller/customerrs/errors.go               |   0
 controller/event/event.go                     |   0
 controller/event/event_test.go                |   0
 controller/eventService/Service.go            |   0
 controller/eventService/utils.go              |   0
 controller/http.go                            |   0
 controller/http_test.go                       |   0
 controller/initialise_test.go                 |   0
 controller/interfaces/change/change.go        |   0
 controller/interfaces/event/service.go        |   0
 controller/interfaces/networkdomain/pnd.go    |   0
 .../interfaces/networkdomain/pndService.go    |   0
 .../interfaces/networkdomain/pndStore.go      |   0
 .../networkelement/networkElement.go          |   0
 .../networkelement/networkElementService.go   |   0
 .../networkelement/networkElementStore.go     |   0
 controller/interfaces/plugin/plugin.go        |   0
 controller/interfaces/plugin/pluginService.go |   0
 controller/interfaces/plugin/pluginStore.go   |   0
 controller/interfaces/rbac/rbacService.go     |   0
 controller/interfaces/rbac/role.go            |   0
 controller/interfaces/rbac/roleStore.go       |   0
 controller/interfaces/rbac/user.go            |   0
 controller/interfaces/rbac/userStore.go       |   0
 controller/interfaces/store/store.go          |   0
 controller/interfaces/transport/transport.go  |   0
 controller/metrics/prometheus.go              |   0
 controller/mocks/Change.go                    |   0
 controller/mocks/Csbi.go                      |   0
 controller/mocks/Device.go                    |   0
 controller/mocks/GNMIClient.go                |   0
 controller/mocks/GNMIServer.go                |   0
 controller/mocks/GNMI_SubscribeClient.go      |   0
 controller/mocks/GNMI_SubscribeServer.go      |   0
 controller/mocks/GenericGoStructClient.go     |   0
 controller/mocks/HandleSubscribeResponse.go   |   0
 controller/mocks/NetworkDomain.go             |   0
 controller/mocks/NetworkElement.go            |   0
 controller/mocks/Plugin.go                    |   0
 .../mocks/PluginRegistryServiceClient.go      |   0
 controller/mocks/Plugin_additions.go          |   0
 controller/mocks/PndService.go                |   0
 controller/mocks/PndStore.go                  |   0
 controller/mocks/Pnd_Additions.go             |   0
 controller/mocks/Role.go                      |   0
 controller/mocks/RoleService.go               |   0
 controller/mocks/RoleStore.go                 |   0
 controller/mocks/Service.go                   |   0
 controller/mocks/Storable.go                  |   0
 controller/mocks/Store.go                     |   0
 controller/mocks/Transport.go                 |   0
 controller/mocks/UnsafeGNMIServer.go          |   0
 controller/mocks/User.go                      |   0
 controller/mocks/UserService.go               |   0
 controller/mocks/UserStore.go                 |   0
 .../mocks/isSubscribeRequest_Request.go       |   0
 .../mocks/isSubscribeResponse_Response.go     |   0
 controller/mocks/isTypedValue_Value.go        |   0
 controller/northbound/client/app.go           |   0
 .../client/configurationManagement.go         |   0
 .../northbound/client/networkElement.go       |   0
 controller/northbound/client/plugin.go        |   0
 controller/northbound/client/pnd.go           |   0
 controller/northbound/client/rbac.go          |   0
 controller/northbound/client/sbi.go           |   0
 controller/northbound/client/submanagement.go |   0
 controller/northbound/server/app.go           |   0
 controller/northbound/server/auth.go          |   0
 .../northbound/server/auth_interceptor.go     |   0
 .../server/auth_interceptor_test.go           |   0
 controller/northbound/server/auth_test.go     |   0
 .../server/configurationmanagement.go         |   0
 controller/northbound/server/csbi.go          |   0
 controller/northbound/server/metrics.go       |   0
 controller/northbound/server/nbi.go           |   0
 .../northbound/server/networkElement.go       |   0
 .../northbound/server/networkElement_test.go  |   0
 controller/northbound/server/plugin.go        |   0
 controller/northbound/server/pnd.go           |   0
 controller/northbound/server/pnd_test.go      |   0
 controller/northbound/server/role.go          |   0
 controller/northbound/server/role_test.go     |   0
 controller/northbound/server/route.go         |   0
 controller/northbound/server/submanagement.go |   0
 .../northbound/server/test_util_test.go       |   0
 controller/northbound/server/topology.go      |   0
 controller/northbound/server/topology_test.go |   0
 controller/northbound/server/user.go          |   0
 controller/northbound/server/user_test.go     |   0
 controller/northbound/server/utils_test.go    |   0
 controller/nucleus/change.go                  |   0
 controller/nucleus/change_test.go             |   0
 controller/nucleus/clientConfig.go            |   0
 .../nucleus/database/mongo-connection.go      |   0
 .../nucleus/databaseNetworkElementStore.go    |   0
 controller/nucleus/databasePluginStore.go     |   0
 controller/nucleus/databasePndStore.go        |   0
 controller/nucleus/genericService.go          |   0
 controller/nucleus/gnmi_transport.go          |   0
 controller/nucleus/gnmi_transport_test.go     |   0
 controller/nucleus/initialise_test.go         |   0
 .../nucleus/memoryNetworkElementStore.go      |   0
 controller/nucleus/memoryPluginStore.go       |   0
 controller/nucleus/memoryPndStore.go          |   0
 controller/nucleus/networkElement.go          |   0
 .../nucleus/networkElementFilesystemStore.go  |   0
 .../networkElementFilesystemStore_test.go     |   0
 controller/nucleus/networkElementService.go   |   0
 .../nucleus/networkElementServiceMock.go      |   0
 .../nucleus/networkElementService_test.go     |   0
 controller/nucleus/networkElementStore.go     |   0
 controller/nucleus/networkElementWatcher.go   |   0
 controller/nucleus/networkElement_test.go     |   0
 controller/nucleus/plugin.go                  |   0
 controller/nucleus/pluginFilesystemStore.go   |   0
 .../nucleus/pluginFilesystemStore_test.go     |   0
 controller/nucleus/pluginService.go           |   0
 controller/nucleus/pluginServiceMock.go       |   0
 controller/nucleus/pluginStore.go             |   0
 controller/nucleus/plugin_test.go             |   0
 controller/nucleus/pndFilesystemStore.go      |   0
 controller/nucleus/pndFilesystemStore_test.go |   0
 controller/nucleus/pndService.go              |   0
 controller/nucleus/pndStore.go                |   0
 controller/nucleus/principalNetworkDomain.go  |   0
 .../nucleus/principalNetworkDomain_test.go    |   0
 controller/nucleus/restconf_transport.go      |   0
 controller/nucleus/restconf_transport_test.go |   0
 .../nucleus/subscriptionQueueHandler.go       |   0
 controller/nucleus/transport.go               |   0
 controller/nucleus/transport_test.go          |   0
 controller/nucleus/types/types.go             |   0
 controller/nucleus/util/gnmi/convert.go       |   0
 controller/nucleus/util/gnmi/notification.go  |   0
 controller/nucleus/util/path/translate.go     |   0
 controller/nucleus/util/path/traverse.go      |   0
 controller/nucleus/util/path/traverse_test.go |   0
 controller/nucleus/util/plugin.go             |   0
 controller/nucleus/util/proto/message.go      |   0
 controller/nucleus/util/proto/message_test.go |   0
 controller/plugin/shared/client.go            |   0
 controller/plugin/shared/interface.go         |   0
 controller/plugin/shared/server.go            |   0
 controller/plugin/shared/util.go              |   0
 controller/rbac/databaseRoleStore.go          |   0
 controller/rbac/databaseUserStore.go          |   0
 controller/rbac/jwtManager.go                 |   0
 controller/rbac/jwtManager_test.go            |   0
 controller/rbac/memoryRoleStore.go            |   0
 controller/rbac/memoryUserStore.go            |   0
 controller/rbac/rbacService.go                |   0
 controller/rbac/rbacTestUtil_test.go          |   0
 controller/rbac/role.go                       |   0
 controller/rbac/roleFileSystemStore.go        |   0
 controller/rbac/roleFileSystemStore_test.go   |   0
 controller/rbac/roleStore.go                  |   0
 controller/rbac/user.go                       |   0
 controller/rbac/userFileSystemStore.go        |   0
 controller/rbac/userFileSystemStore_test.go   |   0
 controller/rbac/userStore.go                  |   0
 controller/store/changeStores.go              |   0
 controller/store/filesystem-settings.go       |   0
 controller/store/genericStore.go              |   0
 controller/store/initialise_test.go           |   0
 controller/store/oldGenericStore.go           |   0
 controller/store/query.go                     |   0
 controller/store/storageMode.go               |   0
 controller/store/utils.go                     |   0
 .../test/arista-interface-response.json       |   0
 .../test/arista-interface-response2.json      |   0
 controller/test/arista-root-response.json     |   0
 .../containerlab/complex-1.0.clab.tmpl.yml    |   0
 controller/test/containerlab/complex-1.0.png  | Bin
 .../test/containerlab/dev.clab.tmpl.yml       |   0
 .../test/containerlab/int01.clab.tmpl.yml     |   0
 controller/test/plugin/csbiAdditions.go       |   0
 .../test/plugin/faulty/csbiAdditions.go       |   0
 controller/test/plugin/faulty/gostructs.go    |   0
 controller/test/plugin/faulty/plugin.yml      |   0
 controller/test/plugin/gostructs.go           |   0
 controller/test/plugin/plugin.yml             |   0
 controller/test/proto/cap-resp-arista-ceos    |   0
 controller/test/proto/req-full-node           |   0
 .../test/proto/req-full-node-arista-ceos      | Bin
 .../test/proto/req-interfaces-arista-ceos     |   0
 .../req-interfaces-interface-arista-ceos      |   0
 controller/test/proto/req-interfaces-wildcard |   0
 controller/test/proto/resp-full-node          |   0
 .../test/proto/resp-full-node-arista-ceos     | Bin
 .../test/proto/resp-interfaces-arista-ceos    |   0
 .../resp-interfaces-interface-arista-ceos     |   0
 .../test/proto/resp-interfaces-wildcard       |   0
 .../proto/resp-set-system-config-hostname     |   0
 controller/test/targets.go                    |   0
 controller/test/terraform/.docker/ca.pem      |   0
 controller/test/terraform/.docker/cert.pem    |   0
 .../test/terraform/.docker/server-cert.pem    |   0
 controller/test/terraform/containers.tf       |   0
 controller/test/terraform/images.tf           |   0
 controller/test/terraform/main.tf             |   0
 controller/test/terraform/providers.tf        |   0
 controller/test/terraform/resources.tf        |   0
 controller/test/terraform/variables.tf        |   0
 controller/test/yang/test-module.go           |   0
 controller/test/yang/test.yang                |   0
 controller/test/yang/yang.go                  |   0
 controller/topology/links/link.go             |   0
 .../topology/nodes/databaseNodeStore.go       |   0
 controller/topology/nodes/node.go             |   0
 controller/topology/nodes/nodeService.go      |   0
 controller/topology/nodes/nodeService_test.go |   0
 controller/topology/nodes/store.go            |   0
 .../ports/configuration/configuration.go      |   0
 controller/topology/ports/port.go             |   0
 controller/topology/ports/portService.go      |   0
 controller/topology/ports/portService_test.go |   0
 controller/topology/ports/portStore.go        |   0
 controller/topology/ports/store.go            |   0
 controller/topology/routing-tables/route.go   |   0
 .../topology/routing-tables/routingTable.go   |   0
 .../routing-tables/routingTableService.go     |   0
 .../routingTableService_test.go               |   0
 .../routing-tables/routingTableStore.go       |   0
 controller/topology/routing-tables/store.go   |   0
 controller/topology/store.go                  |   0
 controller/topology/store/genericStore.go     |   0
 .../topology/store/genericStore_test.go       |   0
 controller/topology/store/query.go            |   0
 controller/topology/topology.go               |   0
 controller/topology/topologyService.go        |   0
 controller/topology/topologyService_test.go   |   0
 controller/topology/topologyStore.go          |   0
 controller/version/version.go                 |   0
 controller/version/version_test.go            |   0
 csbi/.csbi.yaml                               |   0
 csbi/Dockerfile.exec                          |   0
 csbi/LICENSE                                  |   0
 csbi/README.md                                |   0
 csbi/arista.capabilities                      |   0
 csbi/build.go                                 |   0
 csbi/build/ci/.build-container.yml            |   0
 csbi/build/ci/.code-quality-ci.yml            |   0
 csbi/build/ci/.golangci-config/.golangci.yml  |   0
 csbi/build/ci/.security-and-compliance-ci.yml |   0
 csbi/build/ci/.test.yml                       |   0
 csbi/build_test.go                            |   0
 csbi/cmd/csbi/main.go                         |   0
 csbi/cmd/debug/main.go                        |   0
 csbi/cmd/demo/main.go                         |   0
 csbi/cmd/deploy.go                            |   0
 csbi/cmd/discover.go                          |   0
 csbi/cmd/executor/executor.go                 |   0
 csbi/cmd/executor/experiment.yaml             |   0
 csbi/cmd/generate.go                          |   0
 csbi/cmd/hello.go                             |   0
 csbi/cmd/init.go                              |   0
 csbi/cmd/repository.go                        |   0
 csbi/cmd/root.go                              |   0
 csbi/config/config.go                         |   0
 csbi/csbi.Dockerfile                          |   0
 csbi/csbi.Dockerfile.dockerignore             |   0
 csbi/deployment.go                            |   0
 csbi/deployment_test.go                       |   0
 csbi/discover.go                              |   0
 csbi/discover_test.go                         |   0
 csbi/docker-compose.yml                       |   0
 csbi/generate.go                              |   0
 csbi/generate_test.go                         |   0
 csbi/gnmi-target/gnmitarget.Dockerfile        |   0
 .../gnmitarget.Dockerfile.dockerignore        |   0
 .../datasources/prometheus_ds.yml             |   0
 csbi/grpc.go                                  |   0
 csbi/grpc_test.go                             |   0
 csbi/http.go                                  |   0
 csbi/http_test.go                             |   0
 csbi/metrics.go                               |   0
 csbi/model.go                                 |   0
 csbi/orchestrator.go                          |   0
 csbi/orchestrator_test.go                     |   0
 csbi/prometheus/alerts.yml                    |   0
 csbi/prometheus/prometheus.yml                |   0
 csbi/report.xml                               |   0
 csbi/repository.go                            |   0
 csbi/repository_test.go                       |   0
 csbi/resources/Dockerfile                     |   0
 csbi/resources/config.yaml                    |   0
 csbi/resources/csbi.go                        |   0
 csbi/resources/csbiAdditions.go               |   0
 csbi/resources/go.mod                         |   0
 csbi/resources/go.sum                         |   0
 csbi/resources/gostructs.go                   |   0
 csbi/run.go                                   |   0
 csbi/run_test.go                              |   0
 csbi/templates.go                             |   0
 csbi/test.clab.yml                            |   0
 .../gostructs.go                              |   0
 .../experimental/eos/models/arista-cli.yang   |   0
 .../eos/models/arista-eos-types.yang          |   0
 .../eos/models/arista-exp-eos.yang            |   0
 .../eos/models/cert/arista-gnoi-cert.yang     |   0
 .../eos/models/evpn/arista-exp-eos-evpn.yang  |   0
 .../arista-exp-eos-igmpsnooping.yang          |   0
 .../arista-exp-eos-l2protocolforwarding.yang  |   0
 .../eos/models/mlag/arista-exp-eos-mlag.yang  |   0
 .../multicast/arista-exp-eos-multicast.yang   |   0
 .../models/openconfig-component-counters.yang |   0
 .../qos/arista-exp-eos-qos-acl-config.yang    |   0
 .../models/qos/arista-exp-eos-qos-config.yang |   0
 .../eos/models/qos/arista-exp-eos-qos.yang    |   0
 .../eos/models/rpc/arista-rpc-netconf.yang    |   0
 .../models/varp/arista-exp-eos-varp-intf.yang |   0
 .../varp/arista-exp-eos-varp-net-inst.yang    |   0
 .../eos/models/vlan/vlan-translation.yang     |   0
 .../vxlan/arista-exp-eos-vxlan-config.yang    |   0
 .../models/vxlan/arista-exp-eos-vxlan.yang    |   0
 .../models/openconfig/hercules/LICENSE        |   0
 .../yang/openconfig-hercules-interfaces.yang  |   0
 .../openconfig-hercules-platform-chassis.yang |   0
 ...openconfig-hercules-platform-linecard.yang |   0
 .../openconfig-hercules-platform-node.yang    |   0
 .../openconfig-hercules-platform-port.yang    |   0
 .../yang/openconfig-hercules-platform.yang    |   0
 .../yang/openconfig-hercules-qos.yang         |   0
 .../hercules/yang/openconfig-hercules.yang    |   0
 .../testdata/models/openconfig/public/LICENSE |   0
 .../openconfig/public/release/README.md       |   0
 .../public/release/models/acl/.spec.yml       |   0
 .../release/models/acl/openconfig-acl.yang    |   0
 .../acl/openconfig-packet-match-types.yang    |   0
 .../models/acl/openconfig-packet-match.yang   |   0
 .../public/release/models/aft/.spec.yml       |   0
 .../models/aft/openconfig-aft-common.yang     |   0
 .../models/aft/openconfig-aft-ethernet.yang   |   0
 .../models/aft/openconfig-aft-ipv4.yang       |   0
 .../models/aft/openconfig-aft-ipv6.yang       |   0
 .../models/aft/openconfig-aft-mpls.yang       |   0
 .../aft/openconfig-aft-network-instance.yang  |   0
 .../release/models/aft/openconfig-aft-pf.yang |   0
 .../models/aft/openconfig-aft-types.yang      |   0
 .../release/models/aft/openconfig-aft.yang    |   0
 .../public/release/models/bfd/.spec.yml       |   0
 .../release/models/bfd/openconfig-bfd.yang    |   0
 .../public/release/models/bgp/.spec.yml       |   0
 .../openconfig-bgp-common-multiprotocol.yang  |   0
 .../bgp/openconfig-bgp-common-structure.yang  |   0
 .../models/bgp/openconfig-bgp-common.yang     |   0
 .../models/bgp/openconfig-bgp-errors.yang     |   0
 .../models/bgp/openconfig-bgp-global.yang     |   0
 .../models/bgp/openconfig-bgp-neighbor.yang   |   0
 .../models/bgp/openconfig-bgp-peer-group.yang |   0
 .../models/bgp/openconfig-bgp-policy.yang     |   0
 .../models/bgp/openconfig-bgp-types.yang      |   0
 .../release/models/bgp/openconfig-bgp.yang    |   0
 .../public/release/models/catalog/.spec.yml   |   0
 .../catalog/openconfig-catalog-types.yang     |   0
 .../catalog/openconfig-module-catalog.yang    |   0
 .../public/release/models/firewall/.spec.yml  |   0
 .../openconfig-fw-high-availability.yang      |   0
 .../openconfig-fw-link-monitoring.yang        |   0
 .../release/models/interfaces/.spec.yml       |   0
 .../interfaces/openconfig-if-8021x.yang       |   0
 .../interfaces/openconfig-if-aggregate.yang   |   0
 .../openconfig-if-ethernet-ext.yang           |   0
 .../interfaces/openconfig-if-ethernet.yang    |   0
 .../interfaces/openconfig-if-ip-ext.yang      |   0
 .../models/interfaces/openconfig-if-ip.yang   |   0
 .../models/interfaces/openconfig-if-poe.yang  |   0
 .../interfaces/openconfig-if-sdn-ext.yang     |   0
 .../interfaces/openconfig-if-tunnel.yang      |   0
 .../interfaces/openconfig-if-types.yang       |   0
 .../interfaces/openconfig-interfaces.yang     |   0
 .../public/release/models/isis/.spec.yml      |   0
 .../isis/openconfig-isis-lsdb-types.yang      |   0
 .../models/isis/openconfig-isis-lsp.yang      |   0
 .../models/isis/openconfig-isis-policy.yang   |   0
 .../models/isis/openconfig-isis-routing.yang  |   0
 .../models/isis/openconfig-isis-types.yang    |   0
 .../release/models/isis/openconfig-isis.yang  |   0
 .../public/release/models/lacp/.spec.yml      |   0
 .../release/models/lacp/openconfig-lacp.yang  |   0
 .../public/release/models/lldp/.spec.yml      |   0
 .../models/lldp/openconfig-lldp-types.yang    |   0
 .../release/models/lldp/openconfig-lldp.yang  |   0
 .../release/models/local-routing/.spec.yml    |   0
 .../openconfig-local-routing.yang             |   0
 .../public/release/models/macsec/.spec.yml    |   0
 .../macsec/openconfig-macsec-types.yang       |   0
 .../models/macsec/openconfig-macsec.yang      |   0
 .../public/release/models/mpls/.spec.yml      |   0
 .../models/mpls/openconfig-mpls-igp.yang      |   0
 .../models/mpls/openconfig-mpls-ldp.yang      |   0
 .../models/mpls/openconfig-mpls-rsvp.yang     |   0
 .../models/mpls/openconfig-mpls-sr.yang       |   0
 .../models/mpls/openconfig-mpls-static.yang   |   0
 .../models/mpls/openconfig-mpls-te.yang       |   0
 .../models/mpls/openconfig-mpls-types.yang    |   0
 .../release/models/mpls/openconfig-mpls.yang  |   0
 .../public/release/models/multicast/.spec.yml |   0
 .../multicast/openconfig-igmp-types.yang      |   0
 .../models/multicast/openconfig-igmp.yang     |   0
 .../multicast/openconfig-pim-types.yang       |   0
 .../models/multicast/openconfig-pim.yang      |   0
 .../release/models/network-instance/.spec.yml |   0
 .../openconfig-network-instance-l2.yang       |   0
 .../openconfig-network-instance-l3.yang       |   0
 .../openconfig-network-instance-policy.yang   |   0
 .../openconfig-network-instance-types.yang    |   0
 .../openconfig-network-instance.yang          |   0
 .../release/models/openconfig-extensions.yang |   0
 .../public/release/models/openflow/.spec.yml  |   0
 .../openflow/openconfig-openflow-types.yang   |   0
 .../models/openflow/openconfig-openflow.yang  |   0
 .../models/optical-transport/.spec.yml        |   0
 .../openconfig-channel-monitor.yang           |   0
 .../openconfig-optical-amplifier.yang         |   0
 .../openconfig-optical-attenuator.yang        |   0
 .../openconfig-terminal-device.yang           |   0
 .../openconfig-transport-line-common.yang     |   0
 ...penconfig-transport-line-connectivity.yang |   0
 .../openconfig-transport-line-protection.yang |   0
 .../openconfig-transport-types.yang           |   0
 .../openconfig-wavelength-router.yang         |   0
 .../public/release/models/ospf/.spec.yml      |   0
 .../models/ospf/openconfig-ospf-policy.yang   |   0
 .../models/ospf/openconfig-ospf-types.yang    |   0
 .../openconfig-ospfv2-area-interface.yang     |   0
 .../models/ospf/openconfig-ospfv2-area.yang   |   0
 .../models/ospf/openconfig-ospfv2-common.yang |   0
 .../models/ospf/openconfig-ospfv2-global.yang |   0
 .../models/ospf/openconfig-ospfv2-lsdb.yang   |   0
 .../models/ospf/openconfig-ospfv2.yang        |   0
 .../public/release/models/p4rt/.spec.yml      |   0
 .../release/models/p4rt/openconfig-p4rt.yang  |   0
 .../public/release/models/platform/.spec.yml  |   0
 .../platform/openconfig-platform-cpu.yang     |   0
 .../platform/openconfig-platform-ext.yang     |   0
 .../platform/openconfig-platform-fan.yang     |   0
 .../openconfig-platform-linecard.yang         |   0
 ...openconfig-platform-pipeline-counters.yang |   0
 .../platform/openconfig-platform-port.yang    |   0
 .../platform/openconfig-platform-psu.yang     |   0
 .../openconfig-platform-software.yang         |   0
 .../openconfig-platform-transceiver.yang      |   0
 .../platform/openconfig-platform-types.yang   |   0
 .../models/platform/openconfig-platform.yang  |   0
 .../models/policy-forwarding/.spec.yml        |   0
 .../openconfig-pf-forwarding-policies.yang    |   0
 .../openconfig-pf-interfaces.yang             |   0
 .../openconfig-pf-path-groups.yang            |   0
 .../policy-forwarding/openconfig-pf-srte.yang |   0
 .../openconfig-policy-forwarding.yang         |   0
 .../public/release/models/policy/.spec.yml    |   0
 .../policy/openconfig-policy-types.yang       |   0
 .../policy/openconfig-routing-policy.yang     |   0
 .../public/release/models/probes/.spec.yml    |   0
 .../probes/openconfig-probes-types.yang       |   0
 .../models/probes/openconfig-probes.yang      |   0
 .../public/release/models/qos/.spec.yml       |   0
 .../models/qos/openconfig-qos-elements.yang   |   0
 .../models/qos/openconfig-qos-interfaces.yang |   0
 .../models/qos/openconfig-qos-types.yang      |   0
 .../release/models/qos/openconfig-qos.yang    |   0
 .../release/models/relay-agent/.spec.yml      |   0
 .../relay-agent/openconfig-relay-agent.yang   |   0
 .../public/release/models/rib/.spec.yml       |   0
 .../rib/openconfig-rib-bgp-attributes.yang    |   0
 .../models/rib/openconfig-rib-bgp-ext.yang    |   0
 .../openconfig-rib-bgp-shared-attributes.yang |   0
 .../openconfig-rib-bgp-table-attributes.yang  |   0
 .../models/rib/openconfig-rib-bgp-tables.yang |   0
 .../models/rib/openconfig-rib-bgp-types.yang  |   0
 .../models/rib/openconfig-rib-bgp.yang        |   0
 .../public/release/models/sampling/.spec.yml  |   0
 .../sampling/openconfig-sampling-sflow.yang   |   0
 .../release/models/segment-routing/.spec.yml  |   0
 .../openconfig-rsvp-sr-ext.yang               |   0
 .../openconfig-segment-routing-types.yang     |   0
 .../openconfig-segment-routing.yang           |   0
 .../openconfig-srte-policy.yang               |   0
 .../public/release/models/stp/.spec.yml       |   0
 .../stp/openconfig-spanning-tree-types.yang   |   0
 .../models/stp/openconfig-spanning-tree.yang  |   0
 .../public/release/models/system/.spec.yml    |   0
 .../models/system/openconfig-aaa-radius.yang  |   0
 .../models/system/openconfig-aaa-tacacs.yang  |   0
 .../models/system/openconfig-aaa-types.yang   |   0
 .../release/models/system/openconfig-aaa.yang |   0
 .../models/system/openconfig-alarm-types.yang |   0
 .../models/system/openconfig-alarms.yang      |   0
 .../models/system/openconfig-license.yang     |   0
 .../models/system/openconfig-messages.yang    |   0
 .../models/system/openconfig-procmon.yang     |   0
 .../system/openconfig-system-logging.yang     |   0
 .../system/openconfig-system-management.yang  |   0
 .../system/openconfig-system-terminal.yang    |   0
 .../models/system/openconfig-system.yang      |   0
 .../public/release/models/telemetry/.spec.yml |   0
 .../telemetry/openconfig-telemetry-types.yang |   0
 .../telemetry/openconfig-telemetry.yang       |   0
 .../public/release/models/types/.spec.yml     |   0
 .../models/types/openconfig-inet-types.yang   |   0
 .../models/types/openconfig-types.yang        |   0
 .../models/types/openconfig-yang-types.yang   |   0
 .../public/release/models/vlan/.spec.yml      |   0
 .../models/vlan/openconfig-vlan-types.yang    |   0
 .../release/models/vlan/openconfig-vlan.yang  |   0
 .../public/release/models/wifi/.spec.yml      |   0
 .../public/release/models/wifi/README.md      |   0
 .../models/wifi/openconfig-access-points.yang |   0
 .../models/wifi/openconfig-ap-interfaces.yang |   0
 .../models/wifi/openconfig-ap-manager.yang    |   0
 .../models/wifi/openconfig-wifi-mac.yang      |   0
 .../models/wifi/openconfig-wifi-phy.yang      |   0
 .../models/wifi/openconfig-wifi-types.yang    |   0
 .../models/acl/arista-acl-deviations.yang     |   0
 .../models/aft/arista-aft-augments.yang       |   0
 .../models/bfd/arista-bfd-augments.yang       |   0
 .../models/bfd/arista-bfd-deviations.yang     |   0
 .../models/bgp/arista-bgp-augments.yang       |   0
 .../models/bgp/arista-bgp-deviations.yang     |   0
 .../interfaces/arista-intf-augments.yang      |   0
 .../interfaces/arista-intf-deviations.yang    |   0
 .../models/isis/arista-isis-augments.yang     |   0
 .../models/isis/arista-isis-deviations.yang   |   0
 .../models/lacp/arista-lacp-augments.yang     |   0
 .../models/lacp/arista-lacp-deviations.yang   |   0
 .../models/lldp/arista-lldp-augments.yang     |   0
 .../models/lldp/arista-lldp-deviations.yang   |   0
 .../arista-local-routing-deviations.yang      |   0
 .../models/mpls/arista-mpls-augments.yang     |   0
 .../models/mpls/arista-mpls-deviations.yang   |   0
 .../models/multicast/arista-pim-augments.yang |   0
 .../arista-netinst-deviations.yang            |   0
 .../arista-vlan-augments.yang                 |   0
 .../arista-vlan-deviations.yang               |   0
 .../arista-acl-notsupported-deviations.yang   |   0
 .../arista-bfd-notsupported-deviations.yang   |   0
 .../arista-bgp-notsupported-deviations.yang   |   0
 ...ta-interfaces-notsupported-deviations.yang |   0
 .../arista-lacp-notsupported-deviations.yang  |   0
 .../arista-lldp-notsupported-deviations.yang  |   0
 ...local-routing-notsupported-deviations.yang |   0
 ...ista-messages-notsupported-deviations.yang |   0
 ...work-instance-notsupported-deviations.yang |   0
 ...ista-platform-notsupported-deviations.yang |   0
 .../arista-qos-notsupported-deviations.yang   |   0
 ...outing-policy-notsupported-deviations.yang |   0
 ...arista-system-notsupported-deviations.yang |   0
 .../openflow/arista-openflow-deviations.yang  |   0
 .../arista-srte-augments.yang                 |   0
 .../arista-srte-deviations.yang               |   0
 .../models/policy/arista-rpol-augments.yang   |   0
 .../models/policy/arista-rpol-deviations.yang |   0
 .../models/qos/arista-qos-augments.yang       |   0
 .../arista-relay-agent-deviations.yang        |   0
 .../models/system/arista-system-augments.yang |   0
 .../system/arista-system-deviations.yang      |   0
 csbi/testdata/models/third_party/README.md    |   0
 .../models/third_party/ietf/iana-if-type.yang |   0
 .../third_party/ietf/ietf-inet-types.yang     |   0
 .../third_party/ietf/ietf-interfaces.yang     |   0
 .../third_party/ietf/ietf-yang-types.yang     |   0
 csbi/write.go                                 |   0
 csbi/write_test.go                            |   0
 dev_env_data/clab/basic_one_arista.yaml       |   0
 dev_env_data/clab/basic_two_aristas.yaml      |   0
 dev_env_data/clab/basic_two_gnmi_targets.yaml |   0
 dev_env_data/clab/demo.clab.yaml              |   0
 dev_env_data/clab/gosdn.clab.yaml             |   0
 dev_env_data/clab/gosdn_slim.clab.yaml        |   0
 .../docker-compose/basic_docker-compose.yml   |   0
 .../integration-test_docker-compose.yml       |   0
 .../plugin-registry/plugin-store.json         |   0
 dev_env_data/sdn/basic_two_aristas.json       |   0
 docker-compose.yml                            |   0
 docker_volume_backup/.gitkeep                 |   0
 docs/images/logo.png                          | Bin
 docs/images/logo.svg                          |   0
 docs/index.md                                 |   0
 documentation/README.md                       |   0
 documentation/SUMMARY.md                      |   0
 documentation/figures/.gitkeep                |   0
 documentation/figures/nucleus/.gitkeep        |   0
 ...ted_controller_architecture_nucleus.drawio |   0
 ...controller_architecture_nucleus.drawio.png | Bin
 documentation/figures/overview/.gitkeep       |   0
 ...ed_controller_architecture_overview.drawio |   0
 ...ontroller_architecture_overview.drawio.png | Bin
 documentation/figures/plugins/.gitkeep        |   0
 .../plugins/plugin-device-interaction.drawio  |   0
 .../plugin-device-interaction.drawio.png      | Bin
 forks/LICENSE                                 |   0
 forks/README.md                               |   0
 forks/goarista/gnmi/arbitration.go            |   0
 forks/goarista/gnmi/arbitration_test.go       |   0
 forks/goarista/gnmi/client.go                 |   0
 forks/goarista/gnmi/json.go                   |   0
 forks/goarista/gnmi/operation.go              |   0
 forks/goarista/gnmi/operation_test.go         |   0
 forks/goarista/gnmi/path.go                   |   0
 forks/goarista/gnmi/path_test.go              |   0
 forks/google/README.md                        |   0
 forks/google/gnmi/model.go                    |   0
 forks/google/gnmi/modeldata/gostruct/gen.go   |   0
 .../gnmi/modeldata/gostruct/generated.go.wasd |   0
 forks/google/gnmi/modeldata/modeldata.go      |   0
 forks/google/gnmi/server.go                   |   0
 forks/google/gnmi/server_test.go.wasd         |   0
 forks/google/gnmi/util.go                     |   0
 go.mod                                        |   0
 go.sum                                        |   0
 gosdn-cli-showcase.webm                       | Bin
 .../application_tests/appUtility_test.go      |   0
 .../application_tests/application_test.go     |   0
 .../application_tests/eventAssertion_test.go  |   0
 .../example_tests/example_test.go             |   0
 .../integrationTestUtils.go                   |   0
 integration-tests/lab_tests/lab00_test.go     |   0
 .../lab_tests/labUtility_test.go              |   0
 .../networkElement_tests/modelUtility_test.go |   0
 .../networkElement_test.go                    |   0
 integration-tests/rbac_tests/rbac_test.go     |   0
 .../topology_tests/topology_test.go           |   0
 lab-vm/README.md                              |   0
 lab-vm/vm-with-packer/gosdn_vm.pkr.hcl        |   0
 lab-vm/vm-with-packer/http/meta-data          |   0
 lab-vm/vm-with-packer/http/user-data          |   0
 lab-vm/vm-with-packer/scripts/gosdn_clone.sh  |   0
 lab-vm/vm-with-packer/scripts/setup.sh        |   0
 lab-vm/vm-with-vagrant/Vagrantfile            |   0
 makefiles/build/Makefile                      |   0
 makefiles/ci/Makefile                         |   0
 makefiles/clab/Makefile                       |   0
 makefiles/container/Makefile                  |   0
 makefiles/generate/Makefile                   |   0
 mkdocs.yml                                    |   0
 models/generated/README.md                    |   0
 models/generated/arista/additions.patch       |   0
 models/generated/arista/arista.go             |   0
 models/generated/arista/config.yaml           |   0
 models/generated/arista/yang.go               |   0
 models/generated/openconfig/additions.patch   |   0
 models/generated/openconfig/config.yaml       |   0
 models/generated/openconfig/openconfig.go     |   0
 models/generated/openconfig/yang.go           |   0
 plugin-registry/README.md                     |   0
 plugin-registry/main.go                       |   0
 plugin-registry/plugin-registry.Dockerfile    |   0
 .../plugin-registry.Dockerfile.dockerignore   |   0
 .../plugin-registry.debug.Dockerfile          |   0
 ...gin-registry.debug.Dockerfile.dockerignore |   0
 plugin-registry/registry.go                   |   0
 plugin-registry/server.go                     |   0
 plugin-registry/store.go                      |   0
 plugins/README.md                             |   0
 plugins/examples/arista/cmd/main.go           |   0
 plugins/examples/arista/plugin.yaml           |   0
 plugins/examples/openconfig/cmd/main.go       |   0
 plugins/examples/openconfig/plugin.yaml       |   0
 plugins/sdk/deviceModel.go                    |   0
 .../devices/reducer/device.reducer.ts         |   8 +-
 .../devices/view/device.view.table.tsx        | 110 +++++++++++-------
 .../devices/view/device.view.tabs.tsx         |  63 ----------
 .../components/devices/view/device.view.tsx   |  37 +++---
 .../subcomponent/device.view.list-detail.tsx  |  72 ++++++++++++
 .../view_model/device.table.viewmodel.ts      |  17 ++-
 .../view_model/device.tabs.viewmodel.ts       |  32 -----
 .../devices/view_model/device.viewmodel.ts    |  32 ++---
 react-ui/src/index.tsx                        |   1 -
 .../json_viewer/view/json_viewer.scss         |   8 +-
 .../json_viewer/view/json_viewer.view.tsx     |  38 +++---
 .../viewmodel/json_viewer.viewmodel.tsx       |  21 ++--
 react-ui/src/shared/icons/icons.ts            |   4 -
 .../layouts/grid.layout/grid.layout.tsx       |   2 +-
 react-ui/src/shared/style/box.scss            |  65 ++++++++---
 react-ui/src/shared/style/colors.scss         |   3 +-
 renovate.json                                 |   0
 1067 files changed, 271 insertions(+), 245 deletions(-)
 mode change 100644 => 100755 .cobra.yaml
 mode change 100644 => 100755 .devcontainer/Dockerfile
 mode change 100644 => 100755 .devcontainer/devcontainer.json
 mode change 100644 => 100755 .dockerignore
 mode change 100644 => 100755 .editorconfig
 mode change 100644 => 100755 .gitignore
 mode change 100644 => 100755 .gitlab-ci.yml
 mode change 100644 => 100755 .gitlab/ci/.build-binaries.yml
 mode change 100644 => 100755 .gitlab/ci/.build-container-images.yml
 mode change 100644 => 100755 .gitlab/ci/.code-quality-ci.yml
 mode change 100644 => 100755 .gitlab/ci/.mk-docs-deploy.yml
 create mode 100755 .gitlab/ci/.react-ui.yml
 mode change 100644 => 100755 .gitlab/ci/.release-container.yml
 mode change 100644 => 100755 .gitlab/ci/.renovate.yml
 mode change 100644 => 100755 .gitlab/ci/.security-and-compliance-ci.yml
 mode change 100644 => 100755 .gitlab/ci/.test.yml
 mode change 100644 => 100755 .gitlab/ci/gnmi-cert-integration.Dockerfile
 mode change 100644 => 100755 .gitlab/ci/gosdn-integration.Dockerfile
 mode change 100644 => 100755 .gitlab/ci/legacy/.test.yml
 mode change 100644 => 100755 .gitlab/issue_templates/Change Request.md
 mode change 100644 => 100755 .gitlab/issue_templates/Feature Proposal.md
 mode change 100644 => 100755 .gitlab/issue_templates/Issue Template.md
 mode change 100644 => 100755 .gitlab/merge_request_templates/Default.md
 mode change 100644 => 100755 .gitmodules
 mode change 100644 => 100755 .golangci.yml
 mode change 100644 => 100755 LICENSE
 mode change 100644 => 100755 Makefile
 mode change 100644 => 100755 README.md
 mode change 100644 => 100755 api/LICENSE
 mode change 100644 => 100755 api/Makefile
 mode change 100644 => 100755 api/README.md
 mode change 100644 => 100755 api/buf.gen.yaml
 mode change 100644 => 100755 api/buf.work.yaml
 mode change 100644 => 100755 api/cmd/gogen.go
 mode change 100644 => 100755 api/deps/buf.yaml
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/.github/workflows/ci-cpp-build-gnmi.yml
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/BUILD.bazel
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/CONTRIBUTING.md
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/LICENSE
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/README.md
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/WORKSPACE.bazel
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/cache/cache.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/cache/cache_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/cli/cli.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/cli/cli_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/client/cache.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/client/cache_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/client/client.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/client/client_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/client/fake/fake.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/client/fake/fake_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/client/flags/flags_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/client/flags/intmap.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/client/flags/stringlist.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/client/flags/stringmap.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/client/gnmi/client.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/client/gnmi/client_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/client/gnmi/credentials.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/client/grpcutil/lookup.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/client/grpcutil/lookup_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/client/notification.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/client/query.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/client/reconnect.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/client/reconnect_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/client/register.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/client/values.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/cmd/gnmi_cli/gnmi_cli.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/cmd/gnmi_cli/gnmi_cli_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/docker/Dockerfile
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/docker/README.md
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/docker/config/cert.pem
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/docker/config/example.cfg
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/docker/config/key.pem
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/docker/supervisord.conf
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/gnmi_collector.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/gnmi_collector_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/testdata/bad.cfg
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/testdata/bad.crt
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/testdata/bad.key
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/testdata/good.cfg
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/testdata/good.crt
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/testdata/good.key
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/testdata/unparseable.cfg
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/coalesce/coalesce.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/coalesce/coalesce_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/collector/collector.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/collector/collector_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/connection/connection.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/connection/connection_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/ctree/tree.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/ctree/tree_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/errdiff/errdiff.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/errdiff/errdiff_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/errlist/errlist.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/errlist/errlist_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/gnmi_deps.bzl
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/go.mod
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/go.sum
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/latency/latency.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/latency/latency_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/manager/manager.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/manager/manager_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/manager/meta.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/manager/meta_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/match/match.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/match/match_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/metadata/metadata.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/metadata/metadata_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/metadata/yang/gnmi-collector-metadata.yang
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/path/path.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/path/path_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/collector/BUILD.bazel
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/collector/collector.pb.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/collector/collector.proto
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/collector/collector_grpc.pb.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/collector/collector_pb2.py
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/collector/collector_pb2_grpc.py
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/gnmi/BUILD.bazel
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/gnmi/gnmi.pb.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/gnmi/gnmi.proto
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/gnmi/gnmi_grpc.pb.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/gnmi/gnmi_pb2.py
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/gnmi/gnmi_pb2_grpc.py
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/gnmi_ext/BUILD.bazel
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.pb.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.proto
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext_pb2.py
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext_pb2_grpc.py
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/target/BUILD.bazel
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/target/target.pb.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/target/target.proto
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/target/target_pb2.py
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/proto/target/target_pb2_grpc.py
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/subscribe/subscribe.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/subscribe/subscribe_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/target/target.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/target/target_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/testing/fake/gnmi/agent.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/testing/fake/gnmi/client.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/testing/fake/gnmi/cmd/fake_server/README.md
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/testing/fake/gnmi/cmd/fake_server/config.pb.txt
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/testing/fake/gnmi/cmd/fake_server/server.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/testing/fake/gnmi/cmd/gen_fake_config/gen_config.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/testing/fake/gnmi/gnmi_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/testing/fake/proto/fake.pb.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/testing/fake/proto/fake.proto
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/testing/fake/proto/fake_grpc.pb.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/testing/fake/proto/fake_pb2.py
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/testing/fake/proto/fake_pb2_grpc.py
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/testing/fake/queue/fixed_queue.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/testing/fake/queue/queue.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/testing/fake/queue/queue_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/testing/fake/testing/grpc/config/config_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/testing/fake/testing/grpc/config/server_option.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/testing/fake/testing/tls/tls.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/testing/fake/testing/tls/tls_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/value/value.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/value/value_test.go
 mode change 100644 => 100755 api/deps/github.com/openconfig/gnmi/watch/watch.go
 mode change 100644 => 100755 api/go/github.com/openconfig/gnmi/proto/collector/collector.pb.go
 mode change 100644 => 100755 api/go/github.com/openconfig/gnmi/proto/collector/collector_grpc.pb.go
 mode change 100644 => 100755 api/go/github.com/openconfig/gnmi/proto/gnmi/gnmi.pb.go
 mode change 100644 => 100755 api/go/github.com/openconfig/gnmi/proto/gnmi/gnmi_grpc.pb.go
 mode change 100644 => 100755 api/go/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.pb.go
 mode change 100644 => 100755 api/go/github.com/openconfig/gnmi/proto/target/target.pb.go
 mode change 100644 => 100755 api/go/github.com/openconfig/gnmi/testing/fake/proto/fake.pb.go
 mode change 100644 => 100755 api/go/github.com/openconfig/gnmi/testing/fake/proto/fake_grpc.pb.go
 mode change 100644 => 100755 api/go/gosdn/app/app.pb.go
 mode change 100644 => 100755 api/go/gosdn/app/app.pb.gw.go
 mode change 100644 => 100755 api/go/gosdn/app/app_grpc.pb.go
 mode change 100644 => 100755 api/go/gosdn/configurationmanagement/configurationmanagement.pb.go
 mode change 100644 => 100755 api/go/gosdn/configurationmanagement/configurationmanagement.pb.gw.go
 mode change 100644 => 100755 api/go/gosdn/configurationmanagement/configurationmanagement_grpc.pb.go
 mode change 100644 => 100755 api/go/gosdn/conflict/conflict.pb.go
 mode change 100644 => 100755 api/go/gosdn/csbi/csbi.pb.go
 mode change 100644 => 100755 api/go/gosdn/csbi/csbi_grpc.pb.go
 mode change 100644 => 100755 api/go/gosdn/networkelement/networkelement.pb.go
 mode change 100644 => 100755 api/go/gosdn/networkelement/networkelement.pb.gw.go
 mode change 100644 => 100755 api/go/gosdn/networkelement/networkelement_grpc.pb.go
 mode change 100644 => 100755 api/go/gosdn/plugin-internal/plugin-internal.pb.go
 mode change 100644 => 100755 api/go/gosdn/plugin-internal/plugin-internal_grpc.pb.go
 mode change 100644 => 100755 api/go/gosdn/plugin-registry/plugin-registry.pb.go
 mode change 100644 => 100755 api/go/gosdn/plugin-registry/plugin-registry_grpc.pb.go
 mode change 100644 => 100755 api/go/gosdn/plugin/plugin.pb.go
 mode change 100644 => 100755 api/go/gosdn/plugin/plugin_grpc.pb.go
 mode change 100644 => 100755 api/go/gosdn/pnd/pnd.pb.go
 mode change 100644 => 100755 api/go/gosdn/pnd/pnd.pb.gw.go
 mode change 100644 => 100755 api/go/gosdn/pnd/pnd_grpc.pb.go
 mode change 100644 => 100755 api/go/gosdn/rbac/rbac.pb.go
 mode change 100644 => 100755 api/go/gosdn/rbac/rbac.pb.gw.go
 mode change 100644 => 100755 api/go/gosdn/rbac/rbac_grpc.pb.go
 mode change 100644 => 100755 api/go/gosdn/rbac/role.pb.go
 mode change 100644 => 100755 api/go/gosdn/rbac/role.pb.gw.go
 mode change 100644 => 100755 api/go/gosdn/rbac/role_grpc.pb.go
 mode change 100644 => 100755 api/go/gosdn/rbac/user.pb.go
 mode change 100644 => 100755 api/go/gosdn/rbac/user.pb.gw.go
 mode change 100644 => 100755 api/go/gosdn/rbac/user_grpc.pb.go
 mode change 100644 => 100755 api/go/gosdn/southbound/southbound.pb.go
 mode change 100644 => 100755 api/go/gosdn/southbound/southbound_grpc.pb.go
 mode change 100644 => 100755 api/go/gosdn/subscriptionmanagement/subscriptionmanagement.pb.go
 mode change 100644 => 100755 api/go/gosdn/subscriptionmanagement/subscriptionmanagement.pb.gw.go
 mode change 100644 => 100755 api/go/gosdn/subscriptionmanagement/subscriptionmanagement_grpc.pb.go
 mode change 100644 => 100755 api/go/gosdn/topology/link.pb.go
 mode change 100644 => 100755 api/go/gosdn/topology/node.pb.go
 mode change 100644 => 100755 api/go/gosdn/topology/port.pb.go
 mode change 100644 => 100755 api/go/gosdn/topology/route.pb.go
 mode change 100644 => 100755 api/go/gosdn/topology/routingTable.pb.go
 mode change 100644 => 100755 api/go/gosdn/topology/routingTable.pb.gw.go
 mode change 100644 => 100755 api/go/gosdn/topology/routingTable_grpc.pb.go
 mode change 100644 => 100755 api/go/gosdn/topology/topology.pb.go
 mode change 100644 => 100755 api/go/gosdn/topology/topology.pb.gw.go
 mode change 100644 => 100755 api/go/gosdn/topology/topology_grpc.pb.go
 mode change 100644 => 100755 api/go/gosdn/transport/transport.pb.go
 mode change 100644 => 100755 api/openapiv2/gosdn_northbound.swagger.json
 mode change 100644 => 100755 api/proto/buf.lock
 mode change 100644 => 100755 api/proto/buf.yaml
 mode change 100644 => 100755 api/proto/gosdn/app/app.proto
 mode change 100644 => 100755 api/proto/gosdn/configurationmanagement/configurationmanagement.proto
 mode change 100644 => 100755 api/proto/gosdn/conflict/conflict.proto
 mode change 100644 => 100755 api/proto/gosdn/csbi/csbi.proto
 mode change 100644 => 100755 api/proto/gosdn/networkelement/networkelement.proto
 mode change 100644 => 100755 api/proto/gosdn/plugin-internal/plugin-internal.proto
 mode change 100644 => 100755 api/proto/gosdn/plugin-registry/plugin-registry.proto
 mode change 100644 => 100755 api/proto/gosdn/plugin/plugin.proto
 mode change 100644 => 100755 api/proto/gosdn/pnd/pnd.proto
 mode change 100644 => 100755 api/proto/gosdn/rbac/rbac.proto
 mode change 100644 => 100755 api/proto/gosdn/rbac/role.proto
 mode change 100644 => 100755 api/proto/gosdn/rbac/user.proto
 mode change 100644 => 100755 api/proto/gosdn/southbound/southbound.proto
 mode change 100644 => 100755 api/proto/gosdn/subscriptionmanagement/subscriptionmanagement.proto
 mode change 100644 => 100755 api/proto/gosdn/topology/link.proto
 mode change 100644 => 100755 api/proto/gosdn/topology/node.proto
 mode change 100644 => 100755 api/proto/gosdn/topology/port.proto
 mode change 100644 => 100755 api/proto/gosdn/topology/route.proto
 mode change 100644 => 100755 api/proto/gosdn/topology/routingTable.proto
 mode change 100644 => 100755 api/proto/gosdn/topology/topology.proto
 mode change 100644 => 100755 api/proto/gosdn/transport/transport.proto
 mode change 100644 => 100755 api/third_party/validator/validator.proto
 mode change 100644 => 100755 application-framework/event/event.go
 mode change 100644 => 100755 application-framework/event/eventService.go
 mode change 100644 => 100755 application-framework/event/event_test.go
 mode change 100644 => 100755 application-framework/event/topics.go
 mode change 100644 => 100755 application-framework/event/type.go
 mode change 100644 => 100755 application-framework/models/model-handling.go
 mode change 100644 => 100755 application-framework/models/model-handling_test.go
 mode change 100644 => 100755 application-framework/registration/registration.go
 mode change 100644 => 100755 applications/arista-routing-engine/app.go
 mode change 100644 => 100755 applications/arista-routing-engine/arista-routing-engine.Dockerfile
 mode change 100644 => 100755 applications/arista-routing-engine/arista-routing-engine.Dockerfile.dockerignore
 mode change 100644 => 100755 applications/arista-routing-engine/main.go
 mode change 100644 => 100755 applications/arista-routing-engine/network-element.go
 mode change 100644 => 100755 applications/arista-routing-engine/routing.go
 mode change 100644 => 100755 applications/basic-interface-monitoring/app.go
 mode change 100644 => 100755 applications/basic-interface-monitoring/http.go
 mode change 100644 => 100755 applications/basic-interface-monitoring/main.go
 mode change 100644 => 100755 applications/basic-interface-monitoring/network-element.go
 mode change 100644 => 100755 applications/basic-interface-monitoring/webpage/index.html
 mode change 100644 => 100755 applications/hostname-checker/app.go
 mode change 100644 => 100755 applications/hostname-checker/device.go
 mode change 100644 => 100755 applications/hostname-checker/main.go
 mode change 100644 => 100755 applications/inventory-manager/README.md
 mode change 100644 => 100755 applications/inventory-manager/config/config.go
 mode change 100644 => 100755 applications/inventory-manager/example.yml
 mode change 100644 => 100755 applications/inventory-manager/inventory-manager.Dockerfile
 mode change 100644 => 100755 applications/inventory-manager/inventory-manager.Dockerfile.dockerignore
 mode change 100644 => 100755 applications/inventory-manager/inventoryManager/inventoryManager.go
 mode change 100644 => 100755 applications/inventory-manager/inventoryManager/util.go
 mode change 100644 => 100755 applications/inventory-manager/main.go
 mode change 100644 => 100755 applications/venv-manager/Readme.md
 mode change 100644 => 100755 applications/venv-manager/containerlab/containerlab.go
 mode change 100644 => 100755 applications/venv-manager/links/link.go
 mode change 100644 => 100755 applications/venv-manager/main.go
 mode change 100644 => 100755 applications/venv-manager/node/node.go
 mode change 100644 => 100755 applications/venv-manager/port/port.go
 mode change 100644 => 100755 applications/venv-manager/topology/topology.go
 mode change 100644 => 100755 applications/venv-manager/venv-manager.Dockerfile
 mode change 100644 => 100755 applications/venv-manager/venv-manager.Dockerfile.dockerignore
 mode change 100644 => 100755 applications/venv-manager/venv-manager/venv-manager.go
 mode change 100644 => 100755 applications/venv-manager/yang-parser/yang-parser.go
 mode change 100644 => 100755 applications/ws-events/app.go
 mode change 100644 => 100755 applications/ws-events/main.go
 mode change 100644 => 100755 applications/ws-events/ws-events.Dockerfile
 mode change 100644 => 100755 applications/ws-events/ws-events.Dockerfile.dockerignore
 mode change 100644 => 100755 applications/ws-events/ws.go
 mode change 100644 => 100755 cli/LICENSE
 mode change 100644 => 100755 cli/README.md
 mode change 100644 => 100755 cli/adapter/PndAdapter.go
 mode change 100644 => 100755 cli/adapter/PndAdapter_test.go
 mode change 100644 => 100755 cli/build/ci/.security-and-compliance-ci.yml
 mode change 100644 => 100755 cli/build/ci/.test.yml
 mode change 100644 => 100755 cli/cli.Dockerfile
 mode change 100644 => 100755 cli/cli.Dockerfile.dockerignore
 mode change 100644 => 100755 cli/cmd/change.go
 mode change 100644 => 100755 cli/cmd/changeCommit.go
 mode change 100644 => 100755 cli/cmd/changeConfirm.go
 mode change 100644 => 100755 cli/cmd/changeGet.go
 mode change 100644 => 100755 cli/cmd/changeList.go
 mode change 100644 => 100755 cli/cmd/config/.gosdnc.toml
 mode change 100644 => 100755 cli/cmd/list.go
 mode change 100644 => 100755 cli/cmd/login.go
 mode change 100644 => 100755 cli/cmd/logout.go
 mode change 100644 => 100755 cli/cmd/networkElement.go
 mode change 100644 => 100755 cli/cmd/networkElementCreate.go
 mode change 100644 => 100755 cli/cmd/networkElementList.go
 mode change 100644 => 100755 cli/cmd/networkElementPath.go
 mode change 100644 => 100755 cli/cmd/networkElementPathDelete.go
 mode change 100644 => 100755 cli/cmd/networkElementPathGet.go
 mode change 100644 => 100755 cli/cmd/networkElementPathGetIntended.go
 mode change 100644 => 100755 cli/cmd/networkElementPathSet.go
 mode change 100644 => 100755 cli/cmd/networkElementRemove.go
 mode change 100644 => 100755 cli/cmd/networkElementShow.go
 mode change 100644 => 100755 cli/cmd/networkElementSubscribe.go
 mode change 100644 => 100755 cli/cmd/plugin.go
 mode change 100644 => 100755 cli/cmd/pluginList.go
 mode change 100644 => 100755 cli/cmd/pnd.go
 mode change 100644 => 100755 cli/cmd/pndCreate.go
 mode change 100644 => 100755 cli/cmd/pndGet.go
 mode change 100644 => 100755 cli/cmd/pndList.go
 mode change 100644 => 100755 cli/cmd/pndRemove.go
 mode change 100644 => 100755 cli/cmd/pndUse.go
 mode change 100644 => 100755 cli/cmd/prompt.go
 mode change 100644 => 100755 cli/cmd/role.go
 mode change 100644 => 100755 cli/cmd/roleCreate.go
 mode change 100644 => 100755 cli/cmd/roleGetAll.go
 mode change 100644 => 100755 cli/cmd/root.go
 mode change 100644 => 100755 cli/cmd/subManagement.go
 mode change 100644 => 100755 cli/cmd/subManagementGetAll.go
 mode change 100644 => 100755 cli/cmd/subManagementResetAll.go
 mode change 100644 => 100755 cli/cmd/user.go
 mode change 100644 => 100755 cli/cmd/userCreate.go
 mode change 100644 => 100755 cli/cmd/userDelete.go
 mode change 100644 => 100755 cli/cmd/userGet.go
 mode change 100644 => 100755 cli/cmd/userGetAll.go
 mode change 100644 => 100755 cli/cmd/userUpdate.go
 mode change 100644 => 100755 cli/cmd/utils.go
 mode change 100644 => 100755 cli/cmd/utils_test.go
 mode change 100644 => 100755 cli/completer/utils.go
 mode change 100644 => 100755 cli/completer/yangSchemaCompleter.go
 mode change 100644 => 100755 cli/config/.cobra.yaml
 mode change 100644 => 100755 cli/config/gosdnc.toml.example
 mode change 100644 => 100755 cli/main.go
 mode change 100644 => 100755 cli/test/containerlab/integrationtest.clab.tmpl.yml
 mode change 100644 => 100755 cli/test/containerlab/integrationtest_branch.clab.tmpl.yml
 mode change 100644 => 100755 config.js
 mode change 100644 => 100755 controller/ARCHITECTURE.md
 mode change 100644 => 100755 controller/CONTRIBUTING.md
 mode change 100644 => 100755 controller/Dockerfile.debug
 mode change 100644 => 100755 controller/Makefile
 mode change 100644 => 100755 controller/README.md
 mode change 100644 => 100755 controller/api/apiUtil_test.go
 mode change 100644 => 100755 controller/api/api_test.go
 mode change 100644 => 100755 controller/api/api_test.toml
 mode change 100644 => 100755 controller/api/app.go
 mode change 100644 => 100755 controller/api/auth.go
 mode change 100644 => 100755 controller/api/auth_test.go
 mode change 100644 => 100755 controller/api/change.go
 mode change 100644 => 100755 controller/api/configurationManagement.go
 mode change 100644 => 100755 controller/api/grpc.go
 mode change 100644 => 100755 controller/api/initialise_test.go
 mode change 100644 => 100755 controller/api/managedNetworkElement.go
 mode change 100644 => 100755 controller/api/plugin.go
 mode change 100644 => 100755 controller/api/pnd.go
 mode change 100644 => 100755 controller/api/role.go
 mode change 100644 => 100755 controller/api/role_test.go
 mode change 100644 => 100755 controller/api/subManagement.go
 mode change 100644 => 100755 controller/api/user.go
 mode change 100644 => 100755 controller/api/user_test.go
 mode change 100644 => 100755 controller/app/DatabaseStore.go
 mode change 100644 => 100755 controller/app/Service.go
 mode change 100644 => 100755 controller/app/app.go
 mode change 100644 => 100755 controller/app/store.go
 mode change 100644 => 100755 controller/app/utils.go
 mode change 100644 => 100755 controller/cmd/gosdn/main.go
 mode change 100644 => 100755 controller/cmd/root.go
 mode change 100644 => 100755 controller/cmd/version.go
 mode change 100644 => 100755 controller/config/config.go
 mode change 100644 => 100755 controller/config/config_test.go
 mode change 100644 => 100755 controller/config/environment.go
 mode change 100644 => 100755 controller/config/gnmiSubscriptionConfig.go
 mode change 100644 => 100755 controller/configs/.gitkeep
 mode change 100644 => 100755 controller/configs/basic-docker-compose.toml
 mode change 100644 => 100755 controller/configs/containerlab-gosdn.toml.example
 mode change 100644 => 100755 controller/configs/development-gosdn.toml.example
 mode change 100644 => 100755 controller/configs/gNMISubscriptions.txt.example
 mode change 100644 => 100755 controller/configs/integration-test-gosdn.toml
 mode change 100644 => 100755 controller/conflict/versioning.go
 mode change 100644 => 100755 controller/controller.Dockerfile
 mode change 100644 => 100755 controller/controller.Dockerfile.dockerignore
 mode change 100644 => 100755 controller/controller.go
 mode change 100644 => 100755 controller/controller_test.go
 mode change 100644 => 100755 controller/customerrs/errors.go
 mode change 100644 => 100755 controller/event/event.go
 mode change 100644 => 100755 controller/event/event_test.go
 mode change 100644 => 100755 controller/eventService/Service.go
 mode change 100644 => 100755 controller/eventService/utils.go
 mode change 100644 => 100755 controller/http.go
 mode change 100644 => 100755 controller/http_test.go
 mode change 100644 => 100755 controller/initialise_test.go
 mode change 100644 => 100755 controller/interfaces/change/change.go
 mode change 100644 => 100755 controller/interfaces/event/service.go
 mode change 100644 => 100755 controller/interfaces/networkdomain/pnd.go
 mode change 100644 => 100755 controller/interfaces/networkdomain/pndService.go
 mode change 100644 => 100755 controller/interfaces/networkdomain/pndStore.go
 mode change 100644 => 100755 controller/interfaces/networkelement/networkElement.go
 mode change 100644 => 100755 controller/interfaces/networkelement/networkElementService.go
 mode change 100644 => 100755 controller/interfaces/networkelement/networkElementStore.go
 mode change 100644 => 100755 controller/interfaces/plugin/plugin.go
 mode change 100644 => 100755 controller/interfaces/plugin/pluginService.go
 mode change 100644 => 100755 controller/interfaces/plugin/pluginStore.go
 mode change 100644 => 100755 controller/interfaces/rbac/rbacService.go
 mode change 100644 => 100755 controller/interfaces/rbac/role.go
 mode change 100644 => 100755 controller/interfaces/rbac/roleStore.go
 mode change 100644 => 100755 controller/interfaces/rbac/user.go
 mode change 100644 => 100755 controller/interfaces/rbac/userStore.go
 mode change 100644 => 100755 controller/interfaces/store/store.go
 mode change 100644 => 100755 controller/interfaces/transport/transport.go
 mode change 100644 => 100755 controller/metrics/prometheus.go
 mode change 100644 => 100755 controller/mocks/Change.go
 mode change 100644 => 100755 controller/mocks/Csbi.go
 mode change 100644 => 100755 controller/mocks/Device.go
 mode change 100644 => 100755 controller/mocks/GNMIClient.go
 mode change 100644 => 100755 controller/mocks/GNMIServer.go
 mode change 100644 => 100755 controller/mocks/GNMI_SubscribeClient.go
 mode change 100644 => 100755 controller/mocks/GNMI_SubscribeServer.go
 mode change 100644 => 100755 controller/mocks/GenericGoStructClient.go
 mode change 100644 => 100755 controller/mocks/HandleSubscribeResponse.go
 mode change 100644 => 100755 controller/mocks/NetworkDomain.go
 mode change 100644 => 100755 controller/mocks/NetworkElement.go
 mode change 100644 => 100755 controller/mocks/Plugin.go
 mode change 100644 => 100755 controller/mocks/PluginRegistryServiceClient.go
 mode change 100644 => 100755 controller/mocks/Plugin_additions.go
 mode change 100644 => 100755 controller/mocks/PndService.go
 mode change 100644 => 100755 controller/mocks/PndStore.go
 mode change 100644 => 100755 controller/mocks/Pnd_Additions.go
 mode change 100644 => 100755 controller/mocks/Role.go
 mode change 100644 => 100755 controller/mocks/RoleService.go
 mode change 100644 => 100755 controller/mocks/RoleStore.go
 mode change 100644 => 100755 controller/mocks/Service.go
 mode change 100644 => 100755 controller/mocks/Storable.go
 mode change 100644 => 100755 controller/mocks/Store.go
 mode change 100644 => 100755 controller/mocks/Transport.go
 mode change 100644 => 100755 controller/mocks/UnsafeGNMIServer.go
 mode change 100644 => 100755 controller/mocks/User.go
 mode change 100644 => 100755 controller/mocks/UserService.go
 mode change 100644 => 100755 controller/mocks/UserStore.go
 mode change 100644 => 100755 controller/mocks/isSubscribeRequest_Request.go
 mode change 100644 => 100755 controller/mocks/isSubscribeResponse_Response.go
 mode change 100644 => 100755 controller/mocks/isTypedValue_Value.go
 mode change 100644 => 100755 controller/northbound/client/app.go
 mode change 100644 => 100755 controller/northbound/client/configurationManagement.go
 mode change 100644 => 100755 controller/northbound/client/networkElement.go
 mode change 100644 => 100755 controller/northbound/client/plugin.go
 mode change 100644 => 100755 controller/northbound/client/pnd.go
 mode change 100644 => 100755 controller/northbound/client/rbac.go
 mode change 100644 => 100755 controller/northbound/client/sbi.go
 mode change 100644 => 100755 controller/northbound/client/submanagement.go
 mode change 100644 => 100755 controller/northbound/server/app.go
 mode change 100644 => 100755 controller/northbound/server/auth.go
 mode change 100644 => 100755 controller/northbound/server/auth_interceptor.go
 mode change 100644 => 100755 controller/northbound/server/auth_interceptor_test.go
 mode change 100644 => 100755 controller/northbound/server/auth_test.go
 mode change 100644 => 100755 controller/northbound/server/configurationmanagement.go
 mode change 100644 => 100755 controller/northbound/server/csbi.go
 mode change 100644 => 100755 controller/northbound/server/metrics.go
 mode change 100644 => 100755 controller/northbound/server/nbi.go
 mode change 100644 => 100755 controller/northbound/server/networkElement.go
 mode change 100644 => 100755 controller/northbound/server/networkElement_test.go
 mode change 100644 => 100755 controller/northbound/server/plugin.go
 mode change 100644 => 100755 controller/northbound/server/pnd.go
 mode change 100644 => 100755 controller/northbound/server/pnd_test.go
 mode change 100644 => 100755 controller/northbound/server/role.go
 mode change 100644 => 100755 controller/northbound/server/role_test.go
 mode change 100644 => 100755 controller/northbound/server/route.go
 mode change 100644 => 100755 controller/northbound/server/submanagement.go
 mode change 100644 => 100755 controller/northbound/server/test_util_test.go
 mode change 100644 => 100755 controller/northbound/server/topology.go
 mode change 100644 => 100755 controller/northbound/server/topology_test.go
 mode change 100644 => 100755 controller/northbound/server/user.go
 mode change 100644 => 100755 controller/northbound/server/user_test.go
 mode change 100644 => 100755 controller/northbound/server/utils_test.go
 mode change 100644 => 100755 controller/nucleus/change.go
 mode change 100644 => 100755 controller/nucleus/change_test.go
 mode change 100644 => 100755 controller/nucleus/clientConfig.go
 mode change 100644 => 100755 controller/nucleus/database/mongo-connection.go
 mode change 100644 => 100755 controller/nucleus/databaseNetworkElementStore.go
 mode change 100644 => 100755 controller/nucleus/databasePluginStore.go
 mode change 100644 => 100755 controller/nucleus/databasePndStore.go
 mode change 100644 => 100755 controller/nucleus/genericService.go
 mode change 100644 => 100755 controller/nucleus/gnmi_transport.go
 mode change 100644 => 100755 controller/nucleus/gnmi_transport_test.go
 mode change 100644 => 100755 controller/nucleus/initialise_test.go
 mode change 100644 => 100755 controller/nucleus/memoryNetworkElementStore.go
 mode change 100644 => 100755 controller/nucleus/memoryPluginStore.go
 mode change 100644 => 100755 controller/nucleus/memoryPndStore.go
 mode change 100644 => 100755 controller/nucleus/networkElement.go
 mode change 100644 => 100755 controller/nucleus/networkElementFilesystemStore.go
 mode change 100644 => 100755 controller/nucleus/networkElementFilesystemStore_test.go
 mode change 100644 => 100755 controller/nucleus/networkElementService.go
 mode change 100644 => 100755 controller/nucleus/networkElementServiceMock.go
 mode change 100644 => 100755 controller/nucleus/networkElementService_test.go
 mode change 100644 => 100755 controller/nucleus/networkElementStore.go
 mode change 100644 => 100755 controller/nucleus/networkElementWatcher.go
 mode change 100644 => 100755 controller/nucleus/networkElement_test.go
 mode change 100644 => 100755 controller/nucleus/plugin.go
 mode change 100644 => 100755 controller/nucleus/pluginFilesystemStore.go
 mode change 100644 => 100755 controller/nucleus/pluginFilesystemStore_test.go
 mode change 100644 => 100755 controller/nucleus/pluginService.go
 mode change 100644 => 100755 controller/nucleus/pluginServiceMock.go
 mode change 100644 => 100755 controller/nucleus/pluginStore.go
 mode change 100644 => 100755 controller/nucleus/plugin_test.go
 mode change 100644 => 100755 controller/nucleus/pndFilesystemStore.go
 mode change 100644 => 100755 controller/nucleus/pndFilesystemStore_test.go
 mode change 100644 => 100755 controller/nucleus/pndService.go
 mode change 100644 => 100755 controller/nucleus/pndStore.go
 mode change 100644 => 100755 controller/nucleus/principalNetworkDomain.go
 mode change 100644 => 100755 controller/nucleus/principalNetworkDomain_test.go
 mode change 100644 => 100755 controller/nucleus/restconf_transport.go
 mode change 100644 => 100755 controller/nucleus/restconf_transport_test.go
 mode change 100644 => 100755 controller/nucleus/subscriptionQueueHandler.go
 mode change 100644 => 100755 controller/nucleus/transport.go
 mode change 100644 => 100755 controller/nucleus/transport_test.go
 mode change 100644 => 100755 controller/nucleus/types/types.go
 mode change 100644 => 100755 controller/nucleus/util/gnmi/convert.go
 mode change 100644 => 100755 controller/nucleus/util/gnmi/notification.go
 mode change 100644 => 100755 controller/nucleus/util/path/translate.go
 mode change 100644 => 100755 controller/nucleus/util/path/traverse.go
 mode change 100644 => 100755 controller/nucleus/util/path/traverse_test.go
 mode change 100644 => 100755 controller/nucleus/util/plugin.go
 mode change 100644 => 100755 controller/nucleus/util/proto/message.go
 mode change 100644 => 100755 controller/nucleus/util/proto/message_test.go
 mode change 100644 => 100755 controller/plugin/shared/client.go
 mode change 100644 => 100755 controller/plugin/shared/interface.go
 mode change 100644 => 100755 controller/plugin/shared/server.go
 mode change 100644 => 100755 controller/plugin/shared/util.go
 mode change 100644 => 100755 controller/rbac/databaseRoleStore.go
 mode change 100644 => 100755 controller/rbac/databaseUserStore.go
 mode change 100644 => 100755 controller/rbac/jwtManager.go
 mode change 100644 => 100755 controller/rbac/jwtManager_test.go
 mode change 100644 => 100755 controller/rbac/memoryRoleStore.go
 mode change 100644 => 100755 controller/rbac/memoryUserStore.go
 mode change 100644 => 100755 controller/rbac/rbacService.go
 mode change 100644 => 100755 controller/rbac/rbacTestUtil_test.go
 mode change 100644 => 100755 controller/rbac/role.go
 mode change 100644 => 100755 controller/rbac/roleFileSystemStore.go
 mode change 100644 => 100755 controller/rbac/roleFileSystemStore_test.go
 mode change 100644 => 100755 controller/rbac/roleStore.go
 mode change 100644 => 100755 controller/rbac/user.go
 mode change 100644 => 100755 controller/rbac/userFileSystemStore.go
 mode change 100644 => 100755 controller/rbac/userFileSystemStore_test.go
 mode change 100644 => 100755 controller/rbac/userStore.go
 mode change 100644 => 100755 controller/store/changeStores.go
 mode change 100644 => 100755 controller/store/filesystem-settings.go
 mode change 100644 => 100755 controller/store/genericStore.go
 mode change 100644 => 100755 controller/store/initialise_test.go
 mode change 100644 => 100755 controller/store/oldGenericStore.go
 mode change 100644 => 100755 controller/store/query.go
 mode change 100644 => 100755 controller/store/storageMode.go
 mode change 100644 => 100755 controller/store/utils.go
 mode change 100644 => 100755 controller/test/arista-interface-response.json
 mode change 100644 => 100755 controller/test/arista-interface-response2.json
 mode change 100644 => 100755 controller/test/arista-root-response.json
 mode change 100644 => 100755 controller/test/containerlab/complex-1.0.clab.tmpl.yml
 mode change 100644 => 100755 controller/test/containerlab/complex-1.0.png
 mode change 100644 => 100755 controller/test/containerlab/dev.clab.tmpl.yml
 mode change 100644 => 100755 controller/test/containerlab/int01.clab.tmpl.yml
 mode change 100644 => 100755 controller/test/plugin/csbiAdditions.go
 mode change 100644 => 100755 controller/test/plugin/faulty/csbiAdditions.go
 mode change 100644 => 100755 controller/test/plugin/faulty/gostructs.go
 mode change 100644 => 100755 controller/test/plugin/faulty/plugin.yml
 mode change 100644 => 100755 controller/test/plugin/gostructs.go
 mode change 100644 => 100755 controller/test/plugin/plugin.yml
 mode change 100644 => 100755 controller/test/proto/cap-resp-arista-ceos
 mode change 100644 => 100755 controller/test/proto/req-full-node
 mode change 100644 => 100755 controller/test/proto/req-full-node-arista-ceos
 mode change 100644 => 100755 controller/test/proto/req-interfaces-arista-ceos
 mode change 100644 => 100755 controller/test/proto/req-interfaces-interface-arista-ceos
 mode change 100644 => 100755 controller/test/proto/req-interfaces-wildcard
 mode change 100644 => 100755 controller/test/proto/resp-full-node
 mode change 100644 => 100755 controller/test/proto/resp-full-node-arista-ceos
 mode change 100644 => 100755 controller/test/proto/resp-interfaces-arista-ceos
 mode change 100644 => 100755 controller/test/proto/resp-interfaces-interface-arista-ceos
 mode change 100644 => 100755 controller/test/proto/resp-interfaces-wildcard
 mode change 100644 => 100755 controller/test/proto/resp-set-system-config-hostname
 mode change 100644 => 100755 controller/test/targets.go
 mode change 100644 => 100755 controller/test/terraform/.docker/ca.pem
 mode change 100644 => 100755 controller/test/terraform/.docker/cert.pem
 mode change 100644 => 100755 controller/test/terraform/.docker/server-cert.pem
 mode change 100644 => 100755 controller/test/terraform/containers.tf
 mode change 100644 => 100755 controller/test/terraform/images.tf
 mode change 100644 => 100755 controller/test/terraform/main.tf
 mode change 100644 => 100755 controller/test/terraform/providers.tf
 mode change 100644 => 100755 controller/test/terraform/resources.tf
 mode change 100644 => 100755 controller/test/terraform/variables.tf
 mode change 100644 => 100755 controller/test/yang/test-module.go
 mode change 100644 => 100755 controller/test/yang/test.yang
 mode change 100644 => 100755 controller/test/yang/yang.go
 mode change 100644 => 100755 controller/topology/links/link.go
 mode change 100644 => 100755 controller/topology/nodes/databaseNodeStore.go
 mode change 100644 => 100755 controller/topology/nodes/node.go
 mode change 100644 => 100755 controller/topology/nodes/nodeService.go
 mode change 100644 => 100755 controller/topology/nodes/nodeService_test.go
 mode change 100644 => 100755 controller/topology/nodes/store.go
 mode change 100644 => 100755 controller/topology/ports/configuration/configuration.go
 mode change 100644 => 100755 controller/topology/ports/port.go
 mode change 100644 => 100755 controller/topology/ports/portService.go
 mode change 100644 => 100755 controller/topology/ports/portService_test.go
 mode change 100644 => 100755 controller/topology/ports/portStore.go
 mode change 100644 => 100755 controller/topology/ports/store.go
 mode change 100644 => 100755 controller/topology/routing-tables/route.go
 mode change 100644 => 100755 controller/topology/routing-tables/routingTable.go
 mode change 100644 => 100755 controller/topology/routing-tables/routingTableService.go
 mode change 100644 => 100755 controller/topology/routing-tables/routingTableService_test.go
 mode change 100644 => 100755 controller/topology/routing-tables/routingTableStore.go
 mode change 100644 => 100755 controller/topology/routing-tables/store.go
 mode change 100644 => 100755 controller/topology/store.go
 mode change 100644 => 100755 controller/topology/store/genericStore.go
 mode change 100644 => 100755 controller/topology/store/genericStore_test.go
 mode change 100644 => 100755 controller/topology/store/query.go
 mode change 100644 => 100755 controller/topology/topology.go
 mode change 100644 => 100755 controller/topology/topologyService.go
 mode change 100644 => 100755 controller/topology/topologyService_test.go
 mode change 100644 => 100755 controller/topology/topologyStore.go
 mode change 100644 => 100755 controller/version/version.go
 mode change 100644 => 100755 controller/version/version_test.go
 mode change 100644 => 100755 csbi/.csbi.yaml
 mode change 100644 => 100755 csbi/Dockerfile.exec
 mode change 100644 => 100755 csbi/LICENSE
 mode change 100644 => 100755 csbi/README.md
 mode change 100644 => 100755 csbi/arista.capabilities
 mode change 100644 => 100755 csbi/build.go
 mode change 100644 => 100755 csbi/build/ci/.build-container.yml
 mode change 100644 => 100755 csbi/build/ci/.code-quality-ci.yml
 mode change 100644 => 100755 csbi/build/ci/.golangci-config/.golangci.yml
 mode change 100644 => 100755 csbi/build/ci/.security-and-compliance-ci.yml
 mode change 100644 => 100755 csbi/build/ci/.test.yml
 mode change 100644 => 100755 csbi/build_test.go
 mode change 100644 => 100755 csbi/cmd/csbi/main.go
 mode change 100644 => 100755 csbi/cmd/debug/main.go
 mode change 100644 => 100755 csbi/cmd/demo/main.go
 mode change 100644 => 100755 csbi/cmd/deploy.go
 mode change 100644 => 100755 csbi/cmd/discover.go
 mode change 100644 => 100755 csbi/cmd/executor/executor.go
 mode change 100644 => 100755 csbi/cmd/executor/experiment.yaml
 mode change 100644 => 100755 csbi/cmd/generate.go
 mode change 100644 => 100755 csbi/cmd/hello.go
 mode change 100644 => 100755 csbi/cmd/init.go
 mode change 100644 => 100755 csbi/cmd/repository.go
 mode change 100644 => 100755 csbi/cmd/root.go
 mode change 100644 => 100755 csbi/config/config.go
 mode change 100644 => 100755 csbi/csbi.Dockerfile
 mode change 100644 => 100755 csbi/csbi.Dockerfile.dockerignore
 mode change 100644 => 100755 csbi/deployment.go
 mode change 100644 => 100755 csbi/deployment_test.go
 mode change 100644 => 100755 csbi/discover.go
 mode change 100644 => 100755 csbi/discover_test.go
 mode change 100644 => 100755 csbi/docker-compose.yml
 mode change 100644 => 100755 csbi/generate.go
 mode change 100644 => 100755 csbi/generate_test.go
 mode change 100644 => 100755 csbi/gnmi-target/gnmitarget.Dockerfile
 mode change 100644 => 100755 csbi/gnmi-target/gnmitarget.Dockerfile.dockerignore
 mode change 100644 => 100755 csbi/grafana/provisioning/datasources/prometheus_ds.yml
 mode change 100644 => 100755 csbi/grpc.go
 mode change 100644 => 100755 csbi/grpc_test.go
 mode change 100644 => 100755 csbi/http.go
 mode change 100644 => 100755 csbi/http_test.go
 mode change 100644 => 100755 csbi/metrics.go
 mode change 100644 => 100755 csbi/model.go
 mode change 100644 => 100755 csbi/orchestrator.go
 mode change 100644 => 100755 csbi/orchestrator_test.go
 mode change 100644 => 100755 csbi/prometheus/alerts.yml
 mode change 100644 => 100755 csbi/prometheus/prometheus.yml
 mode change 100644 => 100755 csbi/report.xml
 mode change 100644 => 100755 csbi/repository.go
 mode change 100644 => 100755 csbi/repository_test.go
 mode change 100644 => 100755 csbi/resources/Dockerfile
 mode change 100644 => 100755 csbi/resources/config.yaml
 mode change 100644 => 100755 csbi/resources/csbi.go
 mode change 100644 => 100755 csbi/resources/csbiAdditions.go
 mode change 100644 => 100755 csbi/resources/go.mod
 mode change 100644 => 100755 csbi/resources/go.sum
 mode change 100644 => 100755 csbi/resources/gostructs.go
 mode change 100644 => 100755 csbi/run.go
 mode change 100644 => 100755 csbi/run_test.go
 mode change 100644 => 100755 csbi/templates.go
 mode change 100644 => 100755 csbi/test.clab.yml
 mode change 100644 => 100755 csbi/testdata/00000000-0000-0000-0000-000000000000/gostructs.go
 mode change 100644 => 100755 csbi/testdata/models/experimental/eos/models/arista-cli.yang
 mode change 100644 => 100755 csbi/testdata/models/experimental/eos/models/arista-eos-types.yang
 mode change 100644 => 100755 csbi/testdata/models/experimental/eos/models/arista-exp-eos.yang
 mode change 100644 => 100755 csbi/testdata/models/experimental/eos/models/cert/arista-gnoi-cert.yang
 mode change 100644 => 100755 csbi/testdata/models/experimental/eos/models/evpn/arista-exp-eos-evpn.yang
 mode change 100644 => 100755 csbi/testdata/models/experimental/eos/models/igmpsnooping/arista-exp-eos-igmpsnooping.yang
 mode change 100644 => 100755 csbi/testdata/models/experimental/eos/models/l2protocolforwarding/arista-exp-eos-l2protocolforwarding.yang
 mode change 100644 => 100755 csbi/testdata/models/experimental/eos/models/mlag/arista-exp-eos-mlag.yang
 mode change 100644 => 100755 csbi/testdata/models/experimental/eos/models/multicast/arista-exp-eos-multicast.yang
 mode change 100644 => 100755 csbi/testdata/models/experimental/eos/models/openconfig-component-counters.yang
 mode change 100644 => 100755 csbi/testdata/models/experimental/eos/models/qos/arista-exp-eos-qos-acl-config.yang
 mode change 100644 => 100755 csbi/testdata/models/experimental/eos/models/qos/arista-exp-eos-qos-config.yang
 mode change 100644 => 100755 csbi/testdata/models/experimental/eos/models/qos/arista-exp-eos-qos.yang
 mode change 100644 => 100755 csbi/testdata/models/experimental/eos/models/rpc/arista-rpc-netconf.yang
 mode change 100644 => 100755 csbi/testdata/models/experimental/eos/models/varp/arista-exp-eos-varp-intf.yang
 mode change 100644 => 100755 csbi/testdata/models/experimental/eos/models/varp/arista-exp-eos-varp-net-inst.yang
 mode change 100644 => 100755 csbi/testdata/models/experimental/eos/models/vlan/vlan-translation.yang
 mode change 100644 => 100755 csbi/testdata/models/experimental/eos/models/vxlan/arista-exp-eos-vxlan-config.yang
 mode change 100644 => 100755 csbi/testdata/models/experimental/eos/models/vxlan/arista-exp-eos-vxlan.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/hercules/LICENSE
 mode change 100644 => 100755 csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules-interfaces.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules-platform-chassis.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules-platform-linecard.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules-platform-node.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules-platform-port.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules-platform.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules-qos.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/LICENSE
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/README.md
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/acl/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/acl/openconfig-acl.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/acl/openconfig-packet-match-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/acl/openconfig-packet-match.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/aft/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-common.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-ethernet.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-ipv4.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-ipv6.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-mpls.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-network-instance.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-pf.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/bfd/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/bfd/openconfig-bfd.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/bgp/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-common-multiprotocol.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-common-structure.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-common.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-errors.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-global.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-neighbor.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-peer-group.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-policy.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/catalog/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/catalog/openconfig-catalog-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/catalog/openconfig-module-catalog.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/firewall/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/firewall/openconfig-fw-high-availability.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/firewall/openconfig-fw-link-monitoring.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/interfaces/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-8021x.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-aggregate.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-ethernet-ext.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-ethernet.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-ip-ext.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-ip.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-poe.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-sdn-ext.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-tunnel.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-interfaces.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/isis/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/isis/openconfig-isis-lsdb-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/isis/openconfig-isis-lsp.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/isis/openconfig-isis-policy.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/isis/openconfig-isis-routing.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/isis/openconfig-isis-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/isis/openconfig-isis.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/lacp/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/lacp/openconfig-lacp.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/lldp/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/lldp/openconfig-lldp-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/lldp/openconfig-lldp.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/local-routing/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/local-routing/openconfig-local-routing.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/macsec/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/macsec/openconfig-macsec-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/macsec/openconfig-macsec.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/mpls/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls-igp.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls-ldp.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls-rsvp.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls-sr.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls-static.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls-te.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/multicast/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/multicast/openconfig-igmp-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/multicast/openconfig-igmp.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/multicast/openconfig-pim-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/multicast/openconfig-pim.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/network-instance/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/network-instance/openconfig-network-instance-l2.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/network-instance/openconfig-network-instance-l3.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/network-instance/openconfig-network-instance-policy.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/network-instance/openconfig-network-instance-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/network-instance/openconfig-network-instance.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/openconfig-extensions.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/openflow/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/openflow/openconfig-openflow-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/openflow/openconfig-openflow.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/optical-transport/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-channel-monitor.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-optical-amplifier.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-optical-attenuator.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-terminal-device.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-transport-line-common.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-transport-line-connectivity.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-transport-line-protection.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-transport-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-wavelength-router.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/ospf/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospf-policy.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospf-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospfv2-area-interface.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospfv2-area.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospfv2-common.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospfv2-global.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospfv2-lsdb.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospfv2.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/p4rt/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/p4rt/openconfig-p4rt.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/platform/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-cpu.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-ext.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-fan.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-linecard.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-pipeline-counters.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-port.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-psu.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-software.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-transceiver.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/policy-forwarding/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/policy-forwarding/openconfig-pf-forwarding-policies.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/policy-forwarding/openconfig-pf-interfaces.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/policy-forwarding/openconfig-pf-path-groups.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/policy-forwarding/openconfig-pf-srte.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/policy-forwarding/openconfig-policy-forwarding.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/policy/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/policy/openconfig-policy-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/policy/openconfig-routing-policy.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/probes/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/probes/openconfig-probes-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/probes/openconfig-probes.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/qos/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/qos/openconfig-qos-elements.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/qos/openconfig-qos-interfaces.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/qos/openconfig-qos-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/qos/openconfig-qos.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/relay-agent/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/relay-agent/openconfig-relay-agent.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/rib/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/rib/openconfig-rib-bgp-attributes.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/rib/openconfig-rib-bgp-ext.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/rib/openconfig-rib-bgp-shared-attributes.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/rib/openconfig-rib-bgp-table-attributes.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/rib/openconfig-rib-bgp-tables.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/rib/openconfig-rib-bgp-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/rib/openconfig-rib-bgp.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/sampling/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/sampling/openconfig-sampling-sflow.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/segment-routing/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/segment-routing/openconfig-rsvp-sr-ext.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/segment-routing/openconfig-segment-routing-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/segment-routing/openconfig-segment-routing.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/segment-routing/openconfig-srte-policy.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/stp/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/stp/openconfig-spanning-tree-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/stp/openconfig-spanning-tree.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/system/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/system/openconfig-aaa-radius.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/system/openconfig-aaa-tacacs.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/system/openconfig-aaa-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/system/openconfig-aaa.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/system/openconfig-alarm-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/system/openconfig-alarms.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/system/openconfig-license.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/system/openconfig-messages.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/system/openconfig-procmon.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/system/openconfig-system-logging.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/system/openconfig-system-management.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/system/openconfig-system-terminal.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/system/openconfig-system.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/telemetry/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/telemetry/openconfig-telemetry-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/telemetry/openconfig-telemetry.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/types/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/types/openconfig-inet-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/types/openconfig-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/types/openconfig-yang-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/vlan/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/vlan/openconfig-vlan-types.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/vlan/openconfig-vlan.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/wifi/.spec.yml
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/wifi/README.md
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/wifi/openconfig-access-points.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/wifi/openconfig-ap-interfaces.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/wifi/openconfig-ap-manager.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/wifi/openconfig-wifi-mac.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/wifi/openconfig-wifi-phy.yang
 mode change 100644 => 100755 csbi/testdata/models/openconfig/public/release/models/wifi/openconfig-wifi-types.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/acl/arista-acl-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/aft/arista-aft-augments.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/bfd/arista-bfd-augments.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/bfd/arista-bfd-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/bgp/arista-bgp-augments.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/bgp/arista-bgp-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/interfaces/arista-intf-augments.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/interfaces/arista-intf-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/isis/arista-isis-augments.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/isis/arista-isis-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/lacp/arista-lacp-augments.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/lacp/arista-lacp-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/lldp/arista-lldp-augments.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/lldp/arista-lldp-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/local-routing/arista-local-routing-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/mpls/arista-mpls-augments.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/mpls/arista-mpls-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/multicast/arista-pim-augments.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/network-instance/arista-netinst-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/network-instance/arista-vlan-augments.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/network-instance/arista-vlan-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/not-supported/arista-acl-notsupported-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/not-supported/arista-bfd-notsupported-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/not-supported/arista-bgp-notsupported-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/not-supported/arista-interfaces-notsupported-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/not-supported/arista-lacp-notsupported-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/not-supported/arista-lldp-notsupported-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/not-supported/arista-local-routing-notsupported-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/not-supported/arista-messages-notsupported-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/not-supported/arista-network-instance-notsupported-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/not-supported/arista-platform-notsupported-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/not-supported/arista-qos-notsupported-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/not-supported/arista-routing-policy-notsupported-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/not-supported/arista-system-notsupported-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/openflow/arista-openflow-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/policy-forwarding/arista-srte-augments.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/policy-forwarding/arista-srte-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/policy/arista-rpol-augments.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/policy/arista-rpol-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/qos/arista-qos-augments.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/relay-agent/arista-relay-agent-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/system/arista-system-augments.yang
 mode change 100644 => 100755 csbi/testdata/models/release/openconfig/models/system/arista-system-deviations.yang
 mode change 100644 => 100755 csbi/testdata/models/third_party/README.md
 mode change 100644 => 100755 csbi/testdata/models/third_party/ietf/iana-if-type.yang
 mode change 100644 => 100755 csbi/testdata/models/third_party/ietf/ietf-inet-types.yang
 mode change 100644 => 100755 csbi/testdata/models/third_party/ietf/ietf-interfaces.yang
 mode change 100644 => 100755 csbi/testdata/models/third_party/ietf/ietf-yang-types.yang
 mode change 100644 => 100755 csbi/write.go
 mode change 100644 => 100755 csbi/write_test.go
 mode change 100644 => 100755 dev_env_data/clab/basic_one_arista.yaml
 mode change 100644 => 100755 dev_env_data/clab/basic_two_aristas.yaml
 mode change 100644 => 100755 dev_env_data/clab/basic_two_gnmi_targets.yaml
 mode change 100644 => 100755 dev_env_data/clab/demo.clab.yaml
 mode change 100644 => 100755 dev_env_data/clab/gosdn.clab.yaml
 mode change 100644 => 100755 dev_env_data/clab/gosdn_slim.clab.yaml
 mode change 100644 => 100755 dev_env_data/docker-compose/basic_docker-compose.yml
 mode change 100644 => 100755 dev_env_data/docker-compose/integration-test_docker-compose.yml
 mode change 100644 => 100755 dev_env_data/plugin-registry/plugin-store.json
 mode change 100644 => 100755 dev_env_data/sdn/basic_two_aristas.json
 mode change 100644 => 100755 docker-compose.yml
 mode change 100644 => 100755 docker_volume_backup/.gitkeep
 mode change 100644 => 100755 docs/images/logo.png
 mode change 100644 => 100755 docs/images/logo.svg
 mode change 100644 => 100755 docs/index.md
 mode change 100644 => 100755 documentation/README.md
 mode change 100644 => 100755 documentation/SUMMARY.md
 mode change 100644 => 100755 documentation/figures/.gitkeep
 mode change 100644 => 100755 documentation/figures/nucleus/.gitkeep
 mode change 100644 => 100755 documentation/figures/nucleus/updated_controller_architecture_nucleus.drawio
 mode change 100644 => 100755 documentation/figures/nucleus/updated_controller_architecture_nucleus.drawio.png
 mode change 100644 => 100755 documentation/figures/overview/.gitkeep
 mode change 100644 => 100755 documentation/figures/overview/updated_controller_architecture_overview.drawio
 mode change 100644 => 100755 documentation/figures/overview/updated_controller_architecture_overview.drawio.png
 mode change 100644 => 100755 documentation/figures/plugins/.gitkeep
 mode change 100644 => 100755 documentation/figures/plugins/plugin-device-interaction.drawio
 mode change 100644 => 100755 documentation/figures/plugins/plugin-device-interaction.drawio.png
 mode change 100644 => 100755 forks/LICENSE
 mode change 100644 => 100755 forks/README.md
 mode change 100644 => 100755 forks/goarista/gnmi/arbitration.go
 mode change 100644 => 100755 forks/goarista/gnmi/arbitration_test.go
 mode change 100644 => 100755 forks/goarista/gnmi/client.go
 mode change 100644 => 100755 forks/goarista/gnmi/json.go
 mode change 100644 => 100755 forks/goarista/gnmi/operation.go
 mode change 100644 => 100755 forks/goarista/gnmi/operation_test.go
 mode change 100644 => 100755 forks/goarista/gnmi/path.go
 mode change 100644 => 100755 forks/goarista/gnmi/path_test.go
 mode change 100644 => 100755 forks/google/README.md
 mode change 100644 => 100755 forks/google/gnmi/model.go
 mode change 100644 => 100755 forks/google/gnmi/modeldata/gostruct/gen.go
 mode change 100644 => 100755 forks/google/gnmi/modeldata/gostruct/generated.go.wasd
 mode change 100644 => 100755 forks/google/gnmi/modeldata/modeldata.go
 mode change 100644 => 100755 forks/google/gnmi/server.go
 mode change 100644 => 100755 forks/google/gnmi/server_test.go.wasd
 mode change 100644 => 100755 forks/google/gnmi/util.go
 mode change 100644 => 100755 go.mod
 mode change 100644 => 100755 go.sum
 mode change 100644 => 100755 gosdn-cli-showcase.webm
 mode change 100644 => 100755 integration-tests/application_tests/appUtility_test.go
 mode change 100644 => 100755 integration-tests/application_tests/application_test.go
 mode change 100644 => 100755 integration-tests/application_tests/eventAssertion_test.go
 mode change 100644 => 100755 integration-tests/example_tests/example_test.go
 mode change 100644 => 100755 integration-tests/integrationTestUtils/integrationTestUtils.go
 mode change 100644 => 100755 integration-tests/lab_tests/lab00_test.go
 mode change 100644 => 100755 integration-tests/lab_tests/labUtility_test.go
 mode change 100644 => 100755 integration-tests/networkElement_tests/modelUtility_test.go
 mode change 100644 => 100755 integration-tests/networkElement_tests/networkElement_test.go
 mode change 100644 => 100755 integration-tests/rbac_tests/rbac_test.go
 mode change 100644 => 100755 integration-tests/topology_tests/topology_test.go
 mode change 100644 => 100755 lab-vm/README.md
 mode change 100644 => 100755 lab-vm/vm-with-packer/gosdn_vm.pkr.hcl
 mode change 100644 => 100755 lab-vm/vm-with-packer/http/meta-data
 mode change 100644 => 100755 lab-vm/vm-with-packer/http/user-data
 mode change 100644 => 100755 lab-vm/vm-with-packer/scripts/gosdn_clone.sh
 mode change 100644 => 100755 lab-vm/vm-with-packer/scripts/setup.sh
 mode change 100644 => 100755 lab-vm/vm-with-vagrant/Vagrantfile
 mode change 100644 => 100755 makefiles/build/Makefile
 mode change 100644 => 100755 makefiles/ci/Makefile
 mode change 100644 => 100755 makefiles/clab/Makefile
 mode change 100644 => 100755 makefiles/container/Makefile
 mode change 100644 => 100755 makefiles/generate/Makefile
 mode change 100644 => 100755 mkdocs.yml
 mode change 100644 => 100755 models/generated/README.md
 mode change 100644 => 100755 models/generated/arista/additions.patch
 mode change 100644 => 100755 models/generated/arista/arista.go
 mode change 100644 => 100755 models/generated/arista/config.yaml
 mode change 100644 => 100755 models/generated/arista/yang.go
 mode change 100644 => 100755 models/generated/openconfig/additions.patch
 mode change 100644 => 100755 models/generated/openconfig/config.yaml
 mode change 100644 => 100755 models/generated/openconfig/openconfig.go
 mode change 100644 => 100755 models/generated/openconfig/yang.go
 mode change 100644 => 100755 plugin-registry/README.md
 mode change 100644 => 100755 plugin-registry/main.go
 mode change 100644 => 100755 plugin-registry/plugin-registry.Dockerfile
 mode change 100644 => 100755 plugin-registry/plugin-registry.Dockerfile.dockerignore
 mode change 100644 => 100755 plugin-registry/plugin-registry.debug.Dockerfile
 mode change 100644 => 100755 plugin-registry/plugin-registry.debug.Dockerfile.dockerignore
 mode change 100644 => 100755 plugin-registry/registry.go
 mode change 100644 => 100755 plugin-registry/server.go
 mode change 100644 => 100755 plugin-registry/store.go
 mode change 100644 => 100755 plugins/README.md
 mode change 100644 => 100755 plugins/examples/arista/cmd/main.go
 mode change 100644 => 100755 plugins/examples/arista/plugin.yaml
 mode change 100644 => 100755 plugins/examples/openconfig/cmd/main.go
 mode change 100644 => 100755 plugins/examples/openconfig/plugin.yaml
 mode change 100644 => 100755 plugins/sdk/deviceModel.go
 delete mode 100755 react-ui/src/components/devices/view/device.view.tabs.tsx
 create mode 100644 react-ui/src/components/devices/view/subcomponent/device.view.list-detail.tsx
 delete mode 100755 react-ui/src/components/devices/view_model/device.tabs.viewmodel.ts
 delete mode 100755 react-ui/src/shared/icons/icons.ts
 mode change 100644 => 100755 renovate.json

diff --git a/.cobra.yaml b/.cobra.yaml
old mode 100644
new mode 100755
diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
old mode 100644
new mode 100755
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
old mode 100644
new mode 100755
diff --git a/.dockerignore b/.dockerignore
old mode 100644
new mode 100755
diff --git a/.editorconfig b/.editorconfig
old mode 100644
new mode 100755
diff --git a/.gitignore b/.gitignore
old mode 100644
new mode 100755
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
old mode 100644
new mode 100755
diff --git a/.gitlab/ci/.build-binaries.yml b/.gitlab/ci/.build-binaries.yml
old mode 100644
new mode 100755
diff --git a/.gitlab/ci/.build-container-images.yml b/.gitlab/ci/.build-container-images.yml
old mode 100644
new mode 100755
diff --git a/.gitlab/ci/.code-quality-ci.yml b/.gitlab/ci/.code-quality-ci.yml
old mode 100644
new mode 100755
diff --git a/.gitlab/ci/.mk-docs-deploy.yml b/.gitlab/ci/.mk-docs-deploy.yml
old mode 100644
new mode 100755
diff --git a/.gitlab/ci/.react-ui.yml b/.gitlab/ci/.react-ui.yml
new file mode 100755
index 000000000..873b694c8
--- /dev/null
+++ b/.gitlab/ci/.react-ui.yml
@@ -0,0 +1,3 @@
+build-react-ui:
+  stage: build
+  
\ No newline at end of file
diff --git a/.gitlab/ci/.release-container.yml b/.gitlab/ci/.release-container.yml
old mode 100644
new mode 100755
diff --git a/.gitlab/ci/.renovate.yml b/.gitlab/ci/.renovate.yml
old mode 100644
new mode 100755
diff --git a/.gitlab/ci/.security-and-compliance-ci.yml b/.gitlab/ci/.security-and-compliance-ci.yml
old mode 100644
new mode 100755
diff --git a/.gitlab/ci/.test.yml b/.gitlab/ci/.test.yml
old mode 100644
new mode 100755
diff --git a/.gitlab/ci/gnmi-cert-integration.Dockerfile b/.gitlab/ci/gnmi-cert-integration.Dockerfile
old mode 100644
new mode 100755
diff --git a/.gitlab/ci/gosdn-integration.Dockerfile b/.gitlab/ci/gosdn-integration.Dockerfile
old mode 100644
new mode 100755
diff --git a/.gitlab/ci/legacy/.test.yml b/.gitlab/ci/legacy/.test.yml
old mode 100644
new mode 100755
diff --git a/.gitlab/issue_templates/Change Request.md b/.gitlab/issue_templates/Change Request.md
old mode 100644
new mode 100755
diff --git a/.gitlab/issue_templates/Feature Proposal.md b/.gitlab/issue_templates/Feature Proposal.md
old mode 100644
new mode 100755
diff --git a/.gitlab/issue_templates/Issue Template.md b/.gitlab/issue_templates/Issue Template.md
old mode 100644
new mode 100755
diff --git a/.gitlab/merge_request_templates/Default.md b/.gitlab/merge_request_templates/Default.md
old mode 100644
new mode 100755
diff --git a/.gitmodules b/.gitmodules
old mode 100644
new mode 100755
diff --git a/.golangci.yml b/.golangci.yml
old mode 100644
new mode 100755
diff --git a/LICENSE b/LICENSE
old mode 100644
new mode 100755
diff --git a/Makefile b/Makefile
old mode 100644
new mode 100755
diff --git a/README.md b/README.md
old mode 100644
new mode 100755
diff --git a/api/LICENSE b/api/LICENSE
old mode 100644
new mode 100755
diff --git a/api/Makefile b/api/Makefile
old mode 100644
new mode 100755
diff --git a/api/README.md b/api/README.md
old mode 100644
new mode 100755
diff --git a/api/buf.gen.yaml b/api/buf.gen.yaml
old mode 100644
new mode 100755
diff --git a/api/buf.work.yaml b/api/buf.work.yaml
old mode 100644
new mode 100755
diff --git a/api/cmd/gogen.go b/api/cmd/gogen.go
old mode 100644
new mode 100755
diff --git a/api/deps/buf.yaml b/api/deps/buf.yaml
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/.github/workflows/ci-cpp-build-gnmi.yml b/api/deps/github.com/openconfig/gnmi/.github/workflows/ci-cpp-build-gnmi.yml
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/BUILD.bazel b/api/deps/github.com/openconfig/gnmi/BUILD.bazel
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/CONTRIBUTING.md b/api/deps/github.com/openconfig/gnmi/CONTRIBUTING.md
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/LICENSE b/api/deps/github.com/openconfig/gnmi/LICENSE
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/README.md b/api/deps/github.com/openconfig/gnmi/README.md
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/WORKSPACE.bazel b/api/deps/github.com/openconfig/gnmi/WORKSPACE.bazel
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/cache/cache.go b/api/deps/github.com/openconfig/gnmi/cache/cache.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/cache/cache_test.go b/api/deps/github.com/openconfig/gnmi/cache/cache_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/cli/cli.go b/api/deps/github.com/openconfig/gnmi/cli/cli.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/cli/cli_test.go b/api/deps/github.com/openconfig/gnmi/cli/cli_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/client/cache.go b/api/deps/github.com/openconfig/gnmi/client/cache.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/client/cache_test.go b/api/deps/github.com/openconfig/gnmi/client/cache_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/client/client.go b/api/deps/github.com/openconfig/gnmi/client/client.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/client/client_test.go b/api/deps/github.com/openconfig/gnmi/client/client_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/client/fake/fake.go b/api/deps/github.com/openconfig/gnmi/client/fake/fake.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/client/fake/fake_test.go b/api/deps/github.com/openconfig/gnmi/client/fake/fake_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/client/flags/flags_test.go b/api/deps/github.com/openconfig/gnmi/client/flags/flags_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/client/flags/intmap.go b/api/deps/github.com/openconfig/gnmi/client/flags/intmap.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/client/flags/stringlist.go b/api/deps/github.com/openconfig/gnmi/client/flags/stringlist.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/client/flags/stringmap.go b/api/deps/github.com/openconfig/gnmi/client/flags/stringmap.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/client/gnmi/client.go b/api/deps/github.com/openconfig/gnmi/client/gnmi/client.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/client/gnmi/client_test.go b/api/deps/github.com/openconfig/gnmi/client/gnmi/client_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/client/gnmi/credentials.go b/api/deps/github.com/openconfig/gnmi/client/gnmi/credentials.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/client/grpcutil/lookup.go b/api/deps/github.com/openconfig/gnmi/client/grpcutil/lookup.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/client/grpcutil/lookup_test.go b/api/deps/github.com/openconfig/gnmi/client/grpcutil/lookup_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/client/notification.go b/api/deps/github.com/openconfig/gnmi/client/notification.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/client/query.go b/api/deps/github.com/openconfig/gnmi/client/query.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/client/reconnect.go b/api/deps/github.com/openconfig/gnmi/client/reconnect.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/client/reconnect_test.go b/api/deps/github.com/openconfig/gnmi/client/reconnect_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/client/register.go b/api/deps/github.com/openconfig/gnmi/client/register.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/client/values.go b/api/deps/github.com/openconfig/gnmi/client/values.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/cmd/gnmi_cli/gnmi_cli.go b/api/deps/github.com/openconfig/gnmi/cmd/gnmi_cli/gnmi_cli.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/cmd/gnmi_cli/gnmi_cli_test.go b/api/deps/github.com/openconfig/gnmi/cmd/gnmi_cli/gnmi_cli_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/docker/Dockerfile b/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/docker/Dockerfile
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/docker/README.md b/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/docker/README.md
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/docker/config/cert.pem b/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/docker/config/cert.pem
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/docker/config/example.cfg b/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/docker/config/example.cfg
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/docker/config/key.pem b/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/docker/config/key.pem
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/docker/supervisord.conf b/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/docker/supervisord.conf
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/gnmi_collector.go b/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/gnmi_collector.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/gnmi_collector_test.go b/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/gnmi_collector_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/testdata/bad.cfg b/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/testdata/bad.cfg
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/testdata/bad.crt b/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/testdata/bad.crt
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/testdata/bad.key b/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/testdata/bad.key
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/testdata/good.cfg b/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/testdata/good.cfg
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/testdata/good.crt b/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/testdata/good.crt
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/testdata/good.key b/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/testdata/good.key
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/testdata/unparseable.cfg b/api/deps/github.com/openconfig/gnmi/cmd/gnmi_collector/testdata/unparseable.cfg
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/coalesce/coalesce.go b/api/deps/github.com/openconfig/gnmi/coalesce/coalesce.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/coalesce/coalesce_test.go b/api/deps/github.com/openconfig/gnmi/coalesce/coalesce_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/collector/collector.go b/api/deps/github.com/openconfig/gnmi/collector/collector.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/collector/collector_test.go b/api/deps/github.com/openconfig/gnmi/collector/collector_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/connection/connection.go b/api/deps/github.com/openconfig/gnmi/connection/connection.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/connection/connection_test.go b/api/deps/github.com/openconfig/gnmi/connection/connection_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/ctree/tree.go b/api/deps/github.com/openconfig/gnmi/ctree/tree.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/ctree/tree_test.go b/api/deps/github.com/openconfig/gnmi/ctree/tree_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/errdiff/errdiff.go b/api/deps/github.com/openconfig/gnmi/errdiff/errdiff.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/errdiff/errdiff_test.go b/api/deps/github.com/openconfig/gnmi/errdiff/errdiff_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/errlist/errlist.go b/api/deps/github.com/openconfig/gnmi/errlist/errlist.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/errlist/errlist_test.go b/api/deps/github.com/openconfig/gnmi/errlist/errlist_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/gnmi_deps.bzl b/api/deps/github.com/openconfig/gnmi/gnmi_deps.bzl
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/go.mod b/api/deps/github.com/openconfig/gnmi/go.mod
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/go.sum b/api/deps/github.com/openconfig/gnmi/go.sum
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/latency/latency.go b/api/deps/github.com/openconfig/gnmi/latency/latency.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/latency/latency_test.go b/api/deps/github.com/openconfig/gnmi/latency/latency_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/manager/manager.go b/api/deps/github.com/openconfig/gnmi/manager/manager.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/manager/manager_test.go b/api/deps/github.com/openconfig/gnmi/manager/manager_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/manager/meta.go b/api/deps/github.com/openconfig/gnmi/manager/meta.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/manager/meta_test.go b/api/deps/github.com/openconfig/gnmi/manager/meta_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/match/match.go b/api/deps/github.com/openconfig/gnmi/match/match.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/match/match_test.go b/api/deps/github.com/openconfig/gnmi/match/match_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/metadata/metadata.go b/api/deps/github.com/openconfig/gnmi/metadata/metadata.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/metadata/metadata_test.go b/api/deps/github.com/openconfig/gnmi/metadata/metadata_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/metadata/yang/gnmi-collector-metadata.yang b/api/deps/github.com/openconfig/gnmi/metadata/yang/gnmi-collector-metadata.yang
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/path/path.go b/api/deps/github.com/openconfig/gnmi/path/path.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/path/path_test.go b/api/deps/github.com/openconfig/gnmi/path/path_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/collector/BUILD.bazel b/api/deps/github.com/openconfig/gnmi/proto/collector/BUILD.bazel
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/collector/collector.pb.go b/api/deps/github.com/openconfig/gnmi/proto/collector/collector.pb.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/collector/collector.proto b/api/deps/github.com/openconfig/gnmi/proto/collector/collector.proto
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/collector/collector_grpc.pb.go b/api/deps/github.com/openconfig/gnmi/proto/collector/collector_grpc.pb.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/collector/collector_pb2.py b/api/deps/github.com/openconfig/gnmi/proto/collector/collector_pb2.py
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/collector/collector_pb2_grpc.py b/api/deps/github.com/openconfig/gnmi/proto/collector/collector_pb2_grpc.py
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/gnmi/BUILD.bazel b/api/deps/github.com/openconfig/gnmi/proto/gnmi/BUILD.bazel
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/gnmi/gnmi.pb.go b/api/deps/github.com/openconfig/gnmi/proto/gnmi/gnmi.pb.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/gnmi/gnmi.proto b/api/deps/github.com/openconfig/gnmi/proto/gnmi/gnmi.proto
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/gnmi/gnmi_grpc.pb.go b/api/deps/github.com/openconfig/gnmi/proto/gnmi/gnmi_grpc.pb.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/gnmi/gnmi_pb2.py b/api/deps/github.com/openconfig/gnmi/proto/gnmi/gnmi_pb2.py
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/gnmi/gnmi_pb2_grpc.py b/api/deps/github.com/openconfig/gnmi/proto/gnmi/gnmi_pb2_grpc.py
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/gnmi_ext/BUILD.bazel b/api/deps/github.com/openconfig/gnmi/proto/gnmi_ext/BUILD.bazel
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.pb.go b/api/deps/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.pb.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.proto b/api/deps/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.proto
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext_pb2.py b/api/deps/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext_pb2.py
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext_pb2_grpc.py b/api/deps/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext_pb2_grpc.py
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/target/BUILD.bazel b/api/deps/github.com/openconfig/gnmi/proto/target/BUILD.bazel
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/target/target.pb.go b/api/deps/github.com/openconfig/gnmi/proto/target/target.pb.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/target/target.proto b/api/deps/github.com/openconfig/gnmi/proto/target/target.proto
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/target/target_pb2.py b/api/deps/github.com/openconfig/gnmi/proto/target/target_pb2.py
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/proto/target/target_pb2_grpc.py b/api/deps/github.com/openconfig/gnmi/proto/target/target_pb2_grpc.py
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/subscribe/subscribe.go b/api/deps/github.com/openconfig/gnmi/subscribe/subscribe.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/subscribe/subscribe_test.go b/api/deps/github.com/openconfig/gnmi/subscribe/subscribe_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/target/target.go b/api/deps/github.com/openconfig/gnmi/target/target.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/target/target_test.go b/api/deps/github.com/openconfig/gnmi/target/target_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/testing/fake/gnmi/agent.go b/api/deps/github.com/openconfig/gnmi/testing/fake/gnmi/agent.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/testing/fake/gnmi/client.go b/api/deps/github.com/openconfig/gnmi/testing/fake/gnmi/client.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/testing/fake/gnmi/cmd/fake_server/README.md b/api/deps/github.com/openconfig/gnmi/testing/fake/gnmi/cmd/fake_server/README.md
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/testing/fake/gnmi/cmd/fake_server/config.pb.txt b/api/deps/github.com/openconfig/gnmi/testing/fake/gnmi/cmd/fake_server/config.pb.txt
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/testing/fake/gnmi/cmd/fake_server/server.go b/api/deps/github.com/openconfig/gnmi/testing/fake/gnmi/cmd/fake_server/server.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/testing/fake/gnmi/cmd/gen_fake_config/gen_config.go b/api/deps/github.com/openconfig/gnmi/testing/fake/gnmi/cmd/gen_fake_config/gen_config.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/testing/fake/gnmi/gnmi_test.go b/api/deps/github.com/openconfig/gnmi/testing/fake/gnmi/gnmi_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/testing/fake/proto/fake.pb.go b/api/deps/github.com/openconfig/gnmi/testing/fake/proto/fake.pb.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/testing/fake/proto/fake.proto b/api/deps/github.com/openconfig/gnmi/testing/fake/proto/fake.proto
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/testing/fake/proto/fake_grpc.pb.go b/api/deps/github.com/openconfig/gnmi/testing/fake/proto/fake_grpc.pb.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/testing/fake/proto/fake_pb2.py b/api/deps/github.com/openconfig/gnmi/testing/fake/proto/fake_pb2.py
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/testing/fake/proto/fake_pb2_grpc.py b/api/deps/github.com/openconfig/gnmi/testing/fake/proto/fake_pb2_grpc.py
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/testing/fake/queue/fixed_queue.go b/api/deps/github.com/openconfig/gnmi/testing/fake/queue/fixed_queue.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/testing/fake/queue/queue.go b/api/deps/github.com/openconfig/gnmi/testing/fake/queue/queue.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/testing/fake/queue/queue_test.go b/api/deps/github.com/openconfig/gnmi/testing/fake/queue/queue_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/testing/fake/testing/grpc/config/config_test.go b/api/deps/github.com/openconfig/gnmi/testing/fake/testing/grpc/config/config_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/testing/fake/testing/grpc/config/server_option.go b/api/deps/github.com/openconfig/gnmi/testing/fake/testing/grpc/config/server_option.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/testing/fake/testing/tls/tls.go b/api/deps/github.com/openconfig/gnmi/testing/fake/testing/tls/tls.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/testing/fake/testing/tls/tls_test.go b/api/deps/github.com/openconfig/gnmi/testing/fake/testing/tls/tls_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/value/value.go b/api/deps/github.com/openconfig/gnmi/value/value.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/value/value_test.go b/api/deps/github.com/openconfig/gnmi/value/value_test.go
old mode 100644
new mode 100755
diff --git a/api/deps/github.com/openconfig/gnmi/watch/watch.go b/api/deps/github.com/openconfig/gnmi/watch/watch.go
old mode 100644
new mode 100755
diff --git a/api/go/github.com/openconfig/gnmi/proto/collector/collector.pb.go b/api/go/github.com/openconfig/gnmi/proto/collector/collector.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/github.com/openconfig/gnmi/proto/collector/collector_grpc.pb.go b/api/go/github.com/openconfig/gnmi/proto/collector/collector_grpc.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/github.com/openconfig/gnmi/proto/gnmi/gnmi.pb.go b/api/go/github.com/openconfig/gnmi/proto/gnmi/gnmi.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/github.com/openconfig/gnmi/proto/gnmi/gnmi_grpc.pb.go b/api/go/github.com/openconfig/gnmi/proto/gnmi/gnmi_grpc.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.pb.go b/api/go/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/github.com/openconfig/gnmi/proto/target/target.pb.go b/api/go/github.com/openconfig/gnmi/proto/target/target.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/github.com/openconfig/gnmi/testing/fake/proto/fake.pb.go b/api/go/github.com/openconfig/gnmi/testing/fake/proto/fake.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/github.com/openconfig/gnmi/testing/fake/proto/fake_grpc.pb.go b/api/go/github.com/openconfig/gnmi/testing/fake/proto/fake_grpc.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/app/app.pb.go b/api/go/gosdn/app/app.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/app/app.pb.gw.go b/api/go/gosdn/app/app.pb.gw.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/app/app_grpc.pb.go b/api/go/gosdn/app/app_grpc.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/configurationmanagement/configurationmanagement.pb.go b/api/go/gosdn/configurationmanagement/configurationmanagement.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/configurationmanagement/configurationmanagement.pb.gw.go b/api/go/gosdn/configurationmanagement/configurationmanagement.pb.gw.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/configurationmanagement/configurationmanagement_grpc.pb.go b/api/go/gosdn/configurationmanagement/configurationmanagement_grpc.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/conflict/conflict.pb.go b/api/go/gosdn/conflict/conflict.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/csbi/csbi.pb.go b/api/go/gosdn/csbi/csbi.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/csbi/csbi_grpc.pb.go b/api/go/gosdn/csbi/csbi_grpc.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/networkelement/networkelement.pb.go b/api/go/gosdn/networkelement/networkelement.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/networkelement/networkelement.pb.gw.go b/api/go/gosdn/networkelement/networkelement.pb.gw.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/networkelement/networkelement_grpc.pb.go b/api/go/gosdn/networkelement/networkelement_grpc.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/plugin-internal/plugin-internal.pb.go b/api/go/gosdn/plugin-internal/plugin-internal.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/plugin-internal/plugin-internal_grpc.pb.go b/api/go/gosdn/plugin-internal/plugin-internal_grpc.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/plugin-registry/plugin-registry.pb.go b/api/go/gosdn/plugin-registry/plugin-registry.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/plugin-registry/plugin-registry_grpc.pb.go b/api/go/gosdn/plugin-registry/plugin-registry_grpc.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/plugin/plugin.pb.go b/api/go/gosdn/plugin/plugin.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/plugin/plugin_grpc.pb.go b/api/go/gosdn/plugin/plugin_grpc.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/pnd/pnd.pb.go b/api/go/gosdn/pnd/pnd.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/pnd/pnd.pb.gw.go b/api/go/gosdn/pnd/pnd.pb.gw.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/pnd/pnd_grpc.pb.go b/api/go/gosdn/pnd/pnd_grpc.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/rbac/rbac.pb.go b/api/go/gosdn/rbac/rbac.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/rbac/rbac.pb.gw.go b/api/go/gosdn/rbac/rbac.pb.gw.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/rbac/rbac_grpc.pb.go b/api/go/gosdn/rbac/rbac_grpc.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/rbac/role.pb.go b/api/go/gosdn/rbac/role.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/rbac/role.pb.gw.go b/api/go/gosdn/rbac/role.pb.gw.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/rbac/role_grpc.pb.go b/api/go/gosdn/rbac/role_grpc.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/rbac/user.pb.go b/api/go/gosdn/rbac/user.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/rbac/user.pb.gw.go b/api/go/gosdn/rbac/user.pb.gw.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/rbac/user_grpc.pb.go b/api/go/gosdn/rbac/user_grpc.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/southbound/southbound.pb.go b/api/go/gosdn/southbound/southbound.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/southbound/southbound_grpc.pb.go b/api/go/gosdn/southbound/southbound_grpc.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/subscriptionmanagement/subscriptionmanagement.pb.go b/api/go/gosdn/subscriptionmanagement/subscriptionmanagement.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/subscriptionmanagement/subscriptionmanagement.pb.gw.go b/api/go/gosdn/subscriptionmanagement/subscriptionmanagement.pb.gw.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/subscriptionmanagement/subscriptionmanagement_grpc.pb.go b/api/go/gosdn/subscriptionmanagement/subscriptionmanagement_grpc.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/topology/link.pb.go b/api/go/gosdn/topology/link.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/topology/node.pb.go b/api/go/gosdn/topology/node.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/topology/port.pb.go b/api/go/gosdn/topology/port.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/topology/route.pb.go b/api/go/gosdn/topology/route.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/topology/routingTable.pb.go b/api/go/gosdn/topology/routingTable.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/topology/routingTable.pb.gw.go b/api/go/gosdn/topology/routingTable.pb.gw.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/topology/routingTable_grpc.pb.go b/api/go/gosdn/topology/routingTable_grpc.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/topology/topology.pb.go b/api/go/gosdn/topology/topology.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/topology/topology.pb.gw.go b/api/go/gosdn/topology/topology.pb.gw.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/topology/topology_grpc.pb.go b/api/go/gosdn/topology/topology_grpc.pb.go
old mode 100644
new mode 100755
diff --git a/api/go/gosdn/transport/transport.pb.go b/api/go/gosdn/transport/transport.pb.go
old mode 100644
new mode 100755
diff --git a/api/openapiv2/gosdn_northbound.swagger.json b/api/openapiv2/gosdn_northbound.swagger.json
old mode 100644
new mode 100755
diff --git a/api/proto/buf.lock b/api/proto/buf.lock
old mode 100644
new mode 100755
diff --git a/api/proto/buf.yaml b/api/proto/buf.yaml
old mode 100644
new mode 100755
diff --git a/api/proto/gosdn/app/app.proto b/api/proto/gosdn/app/app.proto
old mode 100644
new mode 100755
diff --git a/api/proto/gosdn/configurationmanagement/configurationmanagement.proto b/api/proto/gosdn/configurationmanagement/configurationmanagement.proto
old mode 100644
new mode 100755
diff --git a/api/proto/gosdn/conflict/conflict.proto b/api/proto/gosdn/conflict/conflict.proto
old mode 100644
new mode 100755
diff --git a/api/proto/gosdn/csbi/csbi.proto b/api/proto/gosdn/csbi/csbi.proto
old mode 100644
new mode 100755
diff --git a/api/proto/gosdn/networkelement/networkelement.proto b/api/proto/gosdn/networkelement/networkelement.proto
old mode 100644
new mode 100755
diff --git a/api/proto/gosdn/plugin-internal/plugin-internal.proto b/api/proto/gosdn/plugin-internal/plugin-internal.proto
old mode 100644
new mode 100755
diff --git a/api/proto/gosdn/plugin-registry/plugin-registry.proto b/api/proto/gosdn/plugin-registry/plugin-registry.proto
old mode 100644
new mode 100755
diff --git a/api/proto/gosdn/plugin/plugin.proto b/api/proto/gosdn/plugin/plugin.proto
old mode 100644
new mode 100755
diff --git a/api/proto/gosdn/pnd/pnd.proto b/api/proto/gosdn/pnd/pnd.proto
old mode 100644
new mode 100755
diff --git a/api/proto/gosdn/rbac/rbac.proto b/api/proto/gosdn/rbac/rbac.proto
old mode 100644
new mode 100755
diff --git a/api/proto/gosdn/rbac/role.proto b/api/proto/gosdn/rbac/role.proto
old mode 100644
new mode 100755
diff --git a/api/proto/gosdn/rbac/user.proto b/api/proto/gosdn/rbac/user.proto
old mode 100644
new mode 100755
diff --git a/api/proto/gosdn/southbound/southbound.proto b/api/proto/gosdn/southbound/southbound.proto
old mode 100644
new mode 100755
diff --git a/api/proto/gosdn/subscriptionmanagement/subscriptionmanagement.proto b/api/proto/gosdn/subscriptionmanagement/subscriptionmanagement.proto
old mode 100644
new mode 100755
diff --git a/api/proto/gosdn/topology/link.proto b/api/proto/gosdn/topology/link.proto
old mode 100644
new mode 100755
diff --git a/api/proto/gosdn/topology/node.proto b/api/proto/gosdn/topology/node.proto
old mode 100644
new mode 100755
diff --git a/api/proto/gosdn/topology/port.proto b/api/proto/gosdn/topology/port.proto
old mode 100644
new mode 100755
diff --git a/api/proto/gosdn/topology/route.proto b/api/proto/gosdn/topology/route.proto
old mode 100644
new mode 100755
diff --git a/api/proto/gosdn/topology/routingTable.proto b/api/proto/gosdn/topology/routingTable.proto
old mode 100644
new mode 100755
diff --git a/api/proto/gosdn/topology/topology.proto b/api/proto/gosdn/topology/topology.proto
old mode 100644
new mode 100755
diff --git a/api/proto/gosdn/transport/transport.proto b/api/proto/gosdn/transport/transport.proto
old mode 100644
new mode 100755
diff --git a/api/third_party/validator/validator.proto b/api/third_party/validator/validator.proto
old mode 100644
new mode 100755
diff --git a/application-framework/event/event.go b/application-framework/event/event.go
old mode 100644
new mode 100755
diff --git a/application-framework/event/eventService.go b/application-framework/event/eventService.go
old mode 100644
new mode 100755
diff --git a/application-framework/event/event_test.go b/application-framework/event/event_test.go
old mode 100644
new mode 100755
diff --git a/application-framework/event/topics.go b/application-framework/event/topics.go
old mode 100644
new mode 100755
diff --git a/application-framework/event/type.go b/application-framework/event/type.go
old mode 100644
new mode 100755
diff --git a/application-framework/models/model-handling.go b/application-framework/models/model-handling.go
old mode 100644
new mode 100755
diff --git a/application-framework/models/model-handling_test.go b/application-framework/models/model-handling_test.go
old mode 100644
new mode 100755
diff --git a/application-framework/registration/registration.go b/application-framework/registration/registration.go
old mode 100644
new mode 100755
diff --git a/applications/arista-routing-engine/app.go b/applications/arista-routing-engine/app.go
old mode 100644
new mode 100755
diff --git a/applications/arista-routing-engine/arista-routing-engine.Dockerfile b/applications/arista-routing-engine/arista-routing-engine.Dockerfile
old mode 100644
new mode 100755
diff --git a/applications/arista-routing-engine/arista-routing-engine.Dockerfile.dockerignore b/applications/arista-routing-engine/arista-routing-engine.Dockerfile.dockerignore
old mode 100644
new mode 100755
diff --git a/applications/arista-routing-engine/main.go b/applications/arista-routing-engine/main.go
old mode 100644
new mode 100755
diff --git a/applications/arista-routing-engine/network-element.go b/applications/arista-routing-engine/network-element.go
old mode 100644
new mode 100755
diff --git a/applications/arista-routing-engine/routing.go b/applications/arista-routing-engine/routing.go
old mode 100644
new mode 100755
diff --git a/applications/basic-interface-monitoring/app.go b/applications/basic-interface-monitoring/app.go
old mode 100644
new mode 100755
diff --git a/applications/basic-interface-monitoring/http.go b/applications/basic-interface-monitoring/http.go
old mode 100644
new mode 100755
diff --git a/applications/basic-interface-monitoring/main.go b/applications/basic-interface-monitoring/main.go
old mode 100644
new mode 100755
diff --git a/applications/basic-interface-monitoring/network-element.go b/applications/basic-interface-monitoring/network-element.go
old mode 100644
new mode 100755
diff --git a/applications/basic-interface-monitoring/webpage/index.html b/applications/basic-interface-monitoring/webpage/index.html
old mode 100644
new mode 100755
diff --git a/applications/hostname-checker/app.go b/applications/hostname-checker/app.go
old mode 100644
new mode 100755
diff --git a/applications/hostname-checker/device.go b/applications/hostname-checker/device.go
old mode 100644
new mode 100755
diff --git a/applications/hostname-checker/main.go b/applications/hostname-checker/main.go
old mode 100644
new mode 100755
diff --git a/applications/inventory-manager/README.md b/applications/inventory-manager/README.md
old mode 100644
new mode 100755
diff --git a/applications/inventory-manager/config/config.go b/applications/inventory-manager/config/config.go
old mode 100644
new mode 100755
diff --git a/applications/inventory-manager/example.yml b/applications/inventory-manager/example.yml
old mode 100644
new mode 100755
diff --git a/applications/inventory-manager/inventory-manager.Dockerfile b/applications/inventory-manager/inventory-manager.Dockerfile
old mode 100644
new mode 100755
diff --git a/applications/inventory-manager/inventory-manager.Dockerfile.dockerignore b/applications/inventory-manager/inventory-manager.Dockerfile.dockerignore
old mode 100644
new mode 100755
diff --git a/applications/inventory-manager/inventoryManager/inventoryManager.go b/applications/inventory-manager/inventoryManager/inventoryManager.go
old mode 100644
new mode 100755
diff --git a/applications/inventory-manager/inventoryManager/util.go b/applications/inventory-manager/inventoryManager/util.go
old mode 100644
new mode 100755
diff --git a/applications/inventory-manager/main.go b/applications/inventory-manager/main.go
old mode 100644
new mode 100755
diff --git a/applications/venv-manager/Readme.md b/applications/venv-manager/Readme.md
old mode 100644
new mode 100755
diff --git a/applications/venv-manager/containerlab/containerlab.go b/applications/venv-manager/containerlab/containerlab.go
old mode 100644
new mode 100755
diff --git a/applications/venv-manager/links/link.go b/applications/venv-manager/links/link.go
old mode 100644
new mode 100755
diff --git a/applications/venv-manager/main.go b/applications/venv-manager/main.go
old mode 100644
new mode 100755
diff --git a/applications/venv-manager/node/node.go b/applications/venv-manager/node/node.go
old mode 100644
new mode 100755
diff --git a/applications/venv-manager/port/port.go b/applications/venv-manager/port/port.go
old mode 100644
new mode 100755
diff --git a/applications/venv-manager/topology/topology.go b/applications/venv-manager/topology/topology.go
old mode 100644
new mode 100755
diff --git a/applications/venv-manager/venv-manager.Dockerfile b/applications/venv-manager/venv-manager.Dockerfile
old mode 100644
new mode 100755
diff --git a/applications/venv-manager/venv-manager.Dockerfile.dockerignore b/applications/venv-manager/venv-manager.Dockerfile.dockerignore
old mode 100644
new mode 100755
diff --git a/applications/venv-manager/venv-manager/venv-manager.go b/applications/venv-manager/venv-manager/venv-manager.go
old mode 100644
new mode 100755
diff --git a/applications/venv-manager/yang-parser/yang-parser.go b/applications/venv-manager/yang-parser/yang-parser.go
old mode 100644
new mode 100755
diff --git a/applications/ws-events/app.go b/applications/ws-events/app.go
old mode 100644
new mode 100755
diff --git a/applications/ws-events/main.go b/applications/ws-events/main.go
old mode 100644
new mode 100755
diff --git a/applications/ws-events/ws-events.Dockerfile b/applications/ws-events/ws-events.Dockerfile
old mode 100644
new mode 100755
diff --git a/applications/ws-events/ws-events.Dockerfile.dockerignore b/applications/ws-events/ws-events.Dockerfile.dockerignore
old mode 100644
new mode 100755
diff --git a/applications/ws-events/ws.go b/applications/ws-events/ws.go
old mode 100644
new mode 100755
diff --git a/cli/LICENSE b/cli/LICENSE
old mode 100644
new mode 100755
diff --git a/cli/README.md b/cli/README.md
old mode 100644
new mode 100755
diff --git a/cli/adapter/PndAdapter.go b/cli/adapter/PndAdapter.go
old mode 100644
new mode 100755
diff --git a/cli/adapter/PndAdapter_test.go b/cli/adapter/PndAdapter_test.go
old mode 100644
new mode 100755
diff --git a/cli/build/ci/.security-and-compliance-ci.yml b/cli/build/ci/.security-and-compliance-ci.yml
old mode 100644
new mode 100755
diff --git a/cli/build/ci/.test.yml b/cli/build/ci/.test.yml
old mode 100644
new mode 100755
diff --git a/cli/cli.Dockerfile b/cli/cli.Dockerfile
old mode 100644
new mode 100755
diff --git a/cli/cli.Dockerfile.dockerignore b/cli/cli.Dockerfile.dockerignore
old mode 100644
new mode 100755
diff --git a/cli/cmd/change.go b/cli/cmd/change.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/changeCommit.go b/cli/cmd/changeCommit.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/changeConfirm.go b/cli/cmd/changeConfirm.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/changeGet.go b/cli/cmd/changeGet.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/changeList.go b/cli/cmd/changeList.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/config/.gosdnc.toml b/cli/cmd/config/.gosdnc.toml
old mode 100644
new mode 100755
diff --git a/cli/cmd/list.go b/cli/cmd/list.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/login.go b/cli/cmd/login.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/logout.go b/cli/cmd/logout.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/networkElement.go b/cli/cmd/networkElement.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/networkElementCreate.go b/cli/cmd/networkElementCreate.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/networkElementList.go b/cli/cmd/networkElementList.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/networkElementPath.go b/cli/cmd/networkElementPath.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/networkElementPathDelete.go b/cli/cmd/networkElementPathDelete.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/networkElementPathGet.go b/cli/cmd/networkElementPathGet.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/networkElementPathGetIntended.go b/cli/cmd/networkElementPathGetIntended.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/networkElementPathSet.go b/cli/cmd/networkElementPathSet.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/networkElementRemove.go b/cli/cmd/networkElementRemove.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/networkElementShow.go b/cli/cmd/networkElementShow.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/networkElementSubscribe.go b/cli/cmd/networkElementSubscribe.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/plugin.go b/cli/cmd/plugin.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/pluginList.go b/cli/cmd/pluginList.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/pnd.go b/cli/cmd/pnd.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/pndCreate.go b/cli/cmd/pndCreate.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/pndGet.go b/cli/cmd/pndGet.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/pndList.go b/cli/cmd/pndList.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/pndRemove.go b/cli/cmd/pndRemove.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/pndUse.go b/cli/cmd/pndUse.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/prompt.go b/cli/cmd/prompt.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/role.go b/cli/cmd/role.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/roleCreate.go b/cli/cmd/roleCreate.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/roleGetAll.go b/cli/cmd/roleGetAll.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/root.go b/cli/cmd/root.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/subManagement.go b/cli/cmd/subManagement.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/subManagementGetAll.go b/cli/cmd/subManagementGetAll.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/subManagementResetAll.go b/cli/cmd/subManagementResetAll.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/user.go b/cli/cmd/user.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/userCreate.go b/cli/cmd/userCreate.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/userDelete.go b/cli/cmd/userDelete.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/userGet.go b/cli/cmd/userGet.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/userGetAll.go b/cli/cmd/userGetAll.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/userUpdate.go b/cli/cmd/userUpdate.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/utils.go b/cli/cmd/utils.go
old mode 100644
new mode 100755
diff --git a/cli/cmd/utils_test.go b/cli/cmd/utils_test.go
old mode 100644
new mode 100755
diff --git a/cli/completer/utils.go b/cli/completer/utils.go
old mode 100644
new mode 100755
diff --git a/cli/completer/yangSchemaCompleter.go b/cli/completer/yangSchemaCompleter.go
old mode 100644
new mode 100755
diff --git a/cli/config/.cobra.yaml b/cli/config/.cobra.yaml
old mode 100644
new mode 100755
diff --git a/cli/config/gosdnc.toml.example b/cli/config/gosdnc.toml.example
old mode 100644
new mode 100755
diff --git a/cli/main.go b/cli/main.go
old mode 100644
new mode 100755
diff --git a/cli/test/containerlab/integrationtest.clab.tmpl.yml b/cli/test/containerlab/integrationtest.clab.tmpl.yml
old mode 100644
new mode 100755
diff --git a/cli/test/containerlab/integrationtest_branch.clab.tmpl.yml b/cli/test/containerlab/integrationtest_branch.clab.tmpl.yml
old mode 100644
new mode 100755
diff --git a/config.js b/config.js
old mode 100644
new mode 100755
diff --git a/controller/ARCHITECTURE.md b/controller/ARCHITECTURE.md
old mode 100644
new mode 100755
diff --git a/controller/CONTRIBUTING.md b/controller/CONTRIBUTING.md
old mode 100644
new mode 100755
diff --git a/controller/Dockerfile.debug b/controller/Dockerfile.debug
old mode 100644
new mode 100755
diff --git a/controller/Makefile b/controller/Makefile
old mode 100644
new mode 100755
diff --git a/controller/README.md b/controller/README.md
old mode 100644
new mode 100755
diff --git a/controller/api/apiUtil_test.go b/controller/api/apiUtil_test.go
old mode 100644
new mode 100755
diff --git a/controller/api/api_test.go b/controller/api/api_test.go
old mode 100644
new mode 100755
diff --git a/controller/api/api_test.toml b/controller/api/api_test.toml
old mode 100644
new mode 100755
diff --git a/controller/api/app.go b/controller/api/app.go
old mode 100644
new mode 100755
diff --git a/controller/api/auth.go b/controller/api/auth.go
old mode 100644
new mode 100755
diff --git a/controller/api/auth_test.go b/controller/api/auth_test.go
old mode 100644
new mode 100755
diff --git a/controller/api/change.go b/controller/api/change.go
old mode 100644
new mode 100755
diff --git a/controller/api/configurationManagement.go b/controller/api/configurationManagement.go
old mode 100644
new mode 100755
diff --git a/controller/api/grpc.go b/controller/api/grpc.go
old mode 100644
new mode 100755
diff --git a/controller/api/initialise_test.go b/controller/api/initialise_test.go
old mode 100644
new mode 100755
diff --git a/controller/api/managedNetworkElement.go b/controller/api/managedNetworkElement.go
old mode 100644
new mode 100755
diff --git a/controller/api/plugin.go b/controller/api/plugin.go
old mode 100644
new mode 100755
diff --git a/controller/api/pnd.go b/controller/api/pnd.go
old mode 100644
new mode 100755
diff --git a/controller/api/role.go b/controller/api/role.go
old mode 100644
new mode 100755
diff --git a/controller/api/role_test.go b/controller/api/role_test.go
old mode 100644
new mode 100755
diff --git a/controller/api/subManagement.go b/controller/api/subManagement.go
old mode 100644
new mode 100755
diff --git a/controller/api/user.go b/controller/api/user.go
old mode 100644
new mode 100755
diff --git a/controller/api/user_test.go b/controller/api/user_test.go
old mode 100644
new mode 100755
diff --git a/controller/app/DatabaseStore.go b/controller/app/DatabaseStore.go
old mode 100644
new mode 100755
diff --git a/controller/app/Service.go b/controller/app/Service.go
old mode 100644
new mode 100755
diff --git a/controller/app/app.go b/controller/app/app.go
old mode 100644
new mode 100755
diff --git a/controller/app/store.go b/controller/app/store.go
old mode 100644
new mode 100755
diff --git a/controller/app/utils.go b/controller/app/utils.go
old mode 100644
new mode 100755
diff --git a/controller/cmd/gosdn/main.go b/controller/cmd/gosdn/main.go
old mode 100644
new mode 100755
diff --git a/controller/cmd/root.go b/controller/cmd/root.go
old mode 100644
new mode 100755
diff --git a/controller/cmd/version.go b/controller/cmd/version.go
old mode 100644
new mode 100755
diff --git a/controller/config/config.go b/controller/config/config.go
old mode 100644
new mode 100755
diff --git a/controller/config/config_test.go b/controller/config/config_test.go
old mode 100644
new mode 100755
diff --git a/controller/config/environment.go b/controller/config/environment.go
old mode 100644
new mode 100755
diff --git a/controller/config/gnmiSubscriptionConfig.go b/controller/config/gnmiSubscriptionConfig.go
old mode 100644
new mode 100755
diff --git a/controller/configs/.gitkeep b/controller/configs/.gitkeep
old mode 100644
new mode 100755
diff --git a/controller/configs/basic-docker-compose.toml b/controller/configs/basic-docker-compose.toml
old mode 100644
new mode 100755
diff --git a/controller/configs/containerlab-gosdn.toml.example b/controller/configs/containerlab-gosdn.toml.example
old mode 100644
new mode 100755
diff --git a/controller/configs/development-gosdn.toml.example b/controller/configs/development-gosdn.toml.example
old mode 100644
new mode 100755
diff --git a/controller/configs/gNMISubscriptions.txt.example b/controller/configs/gNMISubscriptions.txt.example
old mode 100644
new mode 100755
diff --git a/controller/configs/integration-test-gosdn.toml b/controller/configs/integration-test-gosdn.toml
old mode 100644
new mode 100755
diff --git a/controller/conflict/versioning.go b/controller/conflict/versioning.go
old mode 100644
new mode 100755
diff --git a/controller/controller.Dockerfile b/controller/controller.Dockerfile
old mode 100644
new mode 100755
diff --git a/controller/controller.Dockerfile.dockerignore b/controller/controller.Dockerfile.dockerignore
old mode 100644
new mode 100755
diff --git a/controller/controller.go b/controller/controller.go
old mode 100644
new mode 100755
diff --git a/controller/controller_test.go b/controller/controller_test.go
old mode 100644
new mode 100755
diff --git a/controller/customerrs/errors.go b/controller/customerrs/errors.go
old mode 100644
new mode 100755
diff --git a/controller/event/event.go b/controller/event/event.go
old mode 100644
new mode 100755
diff --git a/controller/event/event_test.go b/controller/event/event_test.go
old mode 100644
new mode 100755
diff --git a/controller/eventService/Service.go b/controller/eventService/Service.go
old mode 100644
new mode 100755
diff --git a/controller/eventService/utils.go b/controller/eventService/utils.go
old mode 100644
new mode 100755
diff --git a/controller/http.go b/controller/http.go
old mode 100644
new mode 100755
diff --git a/controller/http_test.go b/controller/http_test.go
old mode 100644
new mode 100755
diff --git a/controller/initialise_test.go b/controller/initialise_test.go
old mode 100644
new mode 100755
diff --git a/controller/interfaces/change/change.go b/controller/interfaces/change/change.go
old mode 100644
new mode 100755
diff --git a/controller/interfaces/event/service.go b/controller/interfaces/event/service.go
old mode 100644
new mode 100755
diff --git a/controller/interfaces/networkdomain/pnd.go b/controller/interfaces/networkdomain/pnd.go
old mode 100644
new mode 100755
diff --git a/controller/interfaces/networkdomain/pndService.go b/controller/interfaces/networkdomain/pndService.go
old mode 100644
new mode 100755
diff --git a/controller/interfaces/networkdomain/pndStore.go b/controller/interfaces/networkdomain/pndStore.go
old mode 100644
new mode 100755
diff --git a/controller/interfaces/networkelement/networkElement.go b/controller/interfaces/networkelement/networkElement.go
old mode 100644
new mode 100755
diff --git a/controller/interfaces/networkelement/networkElementService.go b/controller/interfaces/networkelement/networkElementService.go
old mode 100644
new mode 100755
diff --git a/controller/interfaces/networkelement/networkElementStore.go b/controller/interfaces/networkelement/networkElementStore.go
old mode 100644
new mode 100755
diff --git a/controller/interfaces/plugin/plugin.go b/controller/interfaces/plugin/plugin.go
old mode 100644
new mode 100755
diff --git a/controller/interfaces/plugin/pluginService.go b/controller/interfaces/plugin/pluginService.go
old mode 100644
new mode 100755
diff --git a/controller/interfaces/plugin/pluginStore.go b/controller/interfaces/plugin/pluginStore.go
old mode 100644
new mode 100755
diff --git a/controller/interfaces/rbac/rbacService.go b/controller/interfaces/rbac/rbacService.go
old mode 100644
new mode 100755
diff --git a/controller/interfaces/rbac/role.go b/controller/interfaces/rbac/role.go
old mode 100644
new mode 100755
diff --git a/controller/interfaces/rbac/roleStore.go b/controller/interfaces/rbac/roleStore.go
old mode 100644
new mode 100755
diff --git a/controller/interfaces/rbac/user.go b/controller/interfaces/rbac/user.go
old mode 100644
new mode 100755
diff --git a/controller/interfaces/rbac/userStore.go b/controller/interfaces/rbac/userStore.go
old mode 100644
new mode 100755
diff --git a/controller/interfaces/store/store.go b/controller/interfaces/store/store.go
old mode 100644
new mode 100755
diff --git a/controller/interfaces/transport/transport.go b/controller/interfaces/transport/transport.go
old mode 100644
new mode 100755
diff --git a/controller/metrics/prometheus.go b/controller/metrics/prometheus.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/Change.go b/controller/mocks/Change.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/Csbi.go b/controller/mocks/Csbi.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/Device.go b/controller/mocks/Device.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/GNMIClient.go b/controller/mocks/GNMIClient.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/GNMIServer.go b/controller/mocks/GNMIServer.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/GNMI_SubscribeClient.go b/controller/mocks/GNMI_SubscribeClient.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/GNMI_SubscribeServer.go b/controller/mocks/GNMI_SubscribeServer.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/GenericGoStructClient.go b/controller/mocks/GenericGoStructClient.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/HandleSubscribeResponse.go b/controller/mocks/HandleSubscribeResponse.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/NetworkDomain.go b/controller/mocks/NetworkDomain.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/NetworkElement.go b/controller/mocks/NetworkElement.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/Plugin.go b/controller/mocks/Plugin.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/PluginRegistryServiceClient.go b/controller/mocks/PluginRegistryServiceClient.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/Plugin_additions.go b/controller/mocks/Plugin_additions.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/PndService.go b/controller/mocks/PndService.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/PndStore.go b/controller/mocks/PndStore.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/Pnd_Additions.go b/controller/mocks/Pnd_Additions.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/Role.go b/controller/mocks/Role.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/RoleService.go b/controller/mocks/RoleService.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/RoleStore.go b/controller/mocks/RoleStore.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/Service.go b/controller/mocks/Service.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/Storable.go b/controller/mocks/Storable.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/Store.go b/controller/mocks/Store.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/Transport.go b/controller/mocks/Transport.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/UnsafeGNMIServer.go b/controller/mocks/UnsafeGNMIServer.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/User.go b/controller/mocks/User.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/UserService.go b/controller/mocks/UserService.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/UserStore.go b/controller/mocks/UserStore.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/isSubscribeRequest_Request.go b/controller/mocks/isSubscribeRequest_Request.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/isSubscribeResponse_Response.go b/controller/mocks/isSubscribeResponse_Response.go
old mode 100644
new mode 100755
diff --git a/controller/mocks/isTypedValue_Value.go b/controller/mocks/isTypedValue_Value.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/client/app.go b/controller/northbound/client/app.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/client/configurationManagement.go b/controller/northbound/client/configurationManagement.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/client/networkElement.go b/controller/northbound/client/networkElement.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/client/plugin.go b/controller/northbound/client/plugin.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/client/pnd.go b/controller/northbound/client/pnd.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/client/rbac.go b/controller/northbound/client/rbac.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/client/sbi.go b/controller/northbound/client/sbi.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/client/submanagement.go b/controller/northbound/client/submanagement.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/app.go b/controller/northbound/server/app.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/auth.go b/controller/northbound/server/auth.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/auth_interceptor.go b/controller/northbound/server/auth_interceptor.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/auth_interceptor_test.go b/controller/northbound/server/auth_interceptor_test.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/auth_test.go b/controller/northbound/server/auth_test.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/configurationmanagement.go b/controller/northbound/server/configurationmanagement.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/csbi.go b/controller/northbound/server/csbi.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/metrics.go b/controller/northbound/server/metrics.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/nbi.go b/controller/northbound/server/nbi.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/networkElement.go b/controller/northbound/server/networkElement.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/networkElement_test.go b/controller/northbound/server/networkElement_test.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/plugin.go b/controller/northbound/server/plugin.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/pnd.go b/controller/northbound/server/pnd.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/pnd_test.go b/controller/northbound/server/pnd_test.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/role.go b/controller/northbound/server/role.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/role_test.go b/controller/northbound/server/role_test.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/route.go b/controller/northbound/server/route.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/submanagement.go b/controller/northbound/server/submanagement.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/test_util_test.go b/controller/northbound/server/test_util_test.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/topology.go b/controller/northbound/server/topology.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/topology_test.go b/controller/northbound/server/topology_test.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/user.go b/controller/northbound/server/user.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/user_test.go b/controller/northbound/server/user_test.go
old mode 100644
new mode 100755
diff --git a/controller/northbound/server/utils_test.go b/controller/northbound/server/utils_test.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/change.go b/controller/nucleus/change.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/change_test.go b/controller/nucleus/change_test.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/clientConfig.go b/controller/nucleus/clientConfig.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/database/mongo-connection.go b/controller/nucleus/database/mongo-connection.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/databaseNetworkElementStore.go b/controller/nucleus/databaseNetworkElementStore.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/databasePluginStore.go b/controller/nucleus/databasePluginStore.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/databasePndStore.go b/controller/nucleus/databasePndStore.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/genericService.go b/controller/nucleus/genericService.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/gnmi_transport.go b/controller/nucleus/gnmi_transport.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/gnmi_transport_test.go b/controller/nucleus/gnmi_transport_test.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/initialise_test.go b/controller/nucleus/initialise_test.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/memoryNetworkElementStore.go b/controller/nucleus/memoryNetworkElementStore.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/memoryPluginStore.go b/controller/nucleus/memoryPluginStore.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/memoryPndStore.go b/controller/nucleus/memoryPndStore.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/networkElement.go b/controller/nucleus/networkElement.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/networkElementFilesystemStore.go b/controller/nucleus/networkElementFilesystemStore.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/networkElementFilesystemStore_test.go b/controller/nucleus/networkElementFilesystemStore_test.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/networkElementService.go b/controller/nucleus/networkElementService.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/networkElementServiceMock.go b/controller/nucleus/networkElementServiceMock.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/networkElementService_test.go b/controller/nucleus/networkElementService_test.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/networkElementStore.go b/controller/nucleus/networkElementStore.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/networkElementWatcher.go b/controller/nucleus/networkElementWatcher.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/networkElement_test.go b/controller/nucleus/networkElement_test.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/plugin.go b/controller/nucleus/plugin.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/pluginFilesystemStore.go b/controller/nucleus/pluginFilesystemStore.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/pluginFilesystemStore_test.go b/controller/nucleus/pluginFilesystemStore_test.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/pluginService.go b/controller/nucleus/pluginService.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/pluginServiceMock.go b/controller/nucleus/pluginServiceMock.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/pluginStore.go b/controller/nucleus/pluginStore.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/plugin_test.go b/controller/nucleus/plugin_test.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/pndFilesystemStore.go b/controller/nucleus/pndFilesystemStore.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/pndFilesystemStore_test.go b/controller/nucleus/pndFilesystemStore_test.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/pndService.go b/controller/nucleus/pndService.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/pndStore.go b/controller/nucleus/pndStore.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/principalNetworkDomain.go b/controller/nucleus/principalNetworkDomain.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/principalNetworkDomain_test.go b/controller/nucleus/principalNetworkDomain_test.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/restconf_transport.go b/controller/nucleus/restconf_transport.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/restconf_transport_test.go b/controller/nucleus/restconf_transport_test.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/subscriptionQueueHandler.go b/controller/nucleus/subscriptionQueueHandler.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/transport.go b/controller/nucleus/transport.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/transport_test.go b/controller/nucleus/transport_test.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/types/types.go b/controller/nucleus/types/types.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/util/gnmi/convert.go b/controller/nucleus/util/gnmi/convert.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/util/gnmi/notification.go b/controller/nucleus/util/gnmi/notification.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/util/path/translate.go b/controller/nucleus/util/path/translate.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/util/path/traverse.go b/controller/nucleus/util/path/traverse.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/util/path/traverse_test.go b/controller/nucleus/util/path/traverse_test.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/util/plugin.go b/controller/nucleus/util/plugin.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/util/proto/message.go b/controller/nucleus/util/proto/message.go
old mode 100644
new mode 100755
diff --git a/controller/nucleus/util/proto/message_test.go b/controller/nucleus/util/proto/message_test.go
old mode 100644
new mode 100755
diff --git a/controller/plugin/shared/client.go b/controller/plugin/shared/client.go
old mode 100644
new mode 100755
diff --git a/controller/plugin/shared/interface.go b/controller/plugin/shared/interface.go
old mode 100644
new mode 100755
diff --git a/controller/plugin/shared/server.go b/controller/plugin/shared/server.go
old mode 100644
new mode 100755
diff --git a/controller/plugin/shared/util.go b/controller/plugin/shared/util.go
old mode 100644
new mode 100755
diff --git a/controller/rbac/databaseRoleStore.go b/controller/rbac/databaseRoleStore.go
old mode 100644
new mode 100755
diff --git a/controller/rbac/databaseUserStore.go b/controller/rbac/databaseUserStore.go
old mode 100644
new mode 100755
diff --git a/controller/rbac/jwtManager.go b/controller/rbac/jwtManager.go
old mode 100644
new mode 100755
diff --git a/controller/rbac/jwtManager_test.go b/controller/rbac/jwtManager_test.go
old mode 100644
new mode 100755
diff --git a/controller/rbac/memoryRoleStore.go b/controller/rbac/memoryRoleStore.go
old mode 100644
new mode 100755
diff --git a/controller/rbac/memoryUserStore.go b/controller/rbac/memoryUserStore.go
old mode 100644
new mode 100755
diff --git a/controller/rbac/rbacService.go b/controller/rbac/rbacService.go
old mode 100644
new mode 100755
diff --git a/controller/rbac/rbacTestUtil_test.go b/controller/rbac/rbacTestUtil_test.go
old mode 100644
new mode 100755
diff --git a/controller/rbac/role.go b/controller/rbac/role.go
old mode 100644
new mode 100755
diff --git a/controller/rbac/roleFileSystemStore.go b/controller/rbac/roleFileSystemStore.go
old mode 100644
new mode 100755
diff --git a/controller/rbac/roleFileSystemStore_test.go b/controller/rbac/roleFileSystemStore_test.go
old mode 100644
new mode 100755
diff --git a/controller/rbac/roleStore.go b/controller/rbac/roleStore.go
old mode 100644
new mode 100755
diff --git a/controller/rbac/user.go b/controller/rbac/user.go
old mode 100644
new mode 100755
diff --git a/controller/rbac/userFileSystemStore.go b/controller/rbac/userFileSystemStore.go
old mode 100644
new mode 100755
diff --git a/controller/rbac/userFileSystemStore_test.go b/controller/rbac/userFileSystemStore_test.go
old mode 100644
new mode 100755
diff --git a/controller/rbac/userStore.go b/controller/rbac/userStore.go
old mode 100644
new mode 100755
diff --git a/controller/store/changeStores.go b/controller/store/changeStores.go
old mode 100644
new mode 100755
diff --git a/controller/store/filesystem-settings.go b/controller/store/filesystem-settings.go
old mode 100644
new mode 100755
diff --git a/controller/store/genericStore.go b/controller/store/genericStore.go
old mode 100644
new mode 100755
diff --git a/controller/store/initialise_test.go b/controller/store/initialise_test.go
old mode 100644
new mode 100755
diff --git a/controller/store/oldGenericStore.go b/controller/store/oldGenericStore.go
old mode 100644
new mode 100755
diff --git a/controller/store/query.go b/controller/store/query.go
old mode 100644
new mode 100755
diff --git a/controller/store/storageMode.go b/controller/store/storageMode.go
old mode 100644
new mode 100755
diff --git a/controller/store/utils.go b/controller/store/utils.go
old mode 100644
new mode 100755
diff --git a/controller/test/arista-interface-response.json b/controller/test/arista-interface-response.json
old mode 100644
new mode 100755
diff --git a/controller/test/arista-interface-response2.json b/controller/test/arista-interface-response2.json
old mode 100644
new mode 100755
diff --git a/controller/test/arista-root-response.json b/controller/test/arista-root-response.json
old mode 100644
new mode 100755
diff --git a/controller/test/containerlab/complex-1.0.clab.tmpl.yml b/controller/test/containerlab/complex-1.0.clab.tmpl.yml
old mode 100644
new mode 100755
diff --git a/controller/test/containerlab/complex-1.0.png b/controller/test/containerlab/complex-1.0.png
old mode 100644
new mode 100755
diff --git a/controller/test/containerlab/dev.clab.tmpl.yml b/controller/test/containerlab/dev.clab.tmpl.yml
old mode 100644
new mode 100755
diff --git a/controller/test/containerlab/int01.clab.tmpl.yml b/controller/test/containerlab/int01.clab.tmpl.yml
old mode 100644
new mode 100755
diff --git a/controller/test/plugin/csbiAdditions.go b/controller/test/plugin/csbiAdditions.go
old mode 100644
new mode 100755
diff --git a/controller/test/plugin/faulty/csbiAdditions.go b/controller/test/plugin/faulty/csbiAdditions.go
old mode 100644
new mode 100755
diff --git a/controller/test/plugin/faulty/gostructs.go b/controller/test/plugin/faulty/gostructs.go
old mode 100644
new mode 100755
diff --git a/controller/test/plugin/faulty/plugin.yml b/controller/test/plugin/faulty/plugin.yml
old mode 100644
new mode 100755
diff --git a/controller/test/plugin/gostructs.go b/controller/test/plugin/gostructs.go
old mode 100644
new mode 100755
diff --git a/controller/test/plugin/plugin.yml b/controller/test/plugin/plugin.yml
old mode 100644
new mode 100755
diff --git a/controller/test/proto/cap-resp-arista-ceos b/controller/test/proto/cap-resp-arista-ceos
old mode 100644
new mode 100755
diff --git a/controller/test/proto/req-full-node b/controller/test/proto/req-full-node
old mode 100644
new mode 100755
diff --git a/controller/test/proto/req-full-node-arista-ceos b/controller/test/proto/req-full-node-arista-ceos
old mode 100644
new mode 100755
diff --git a/controller/test/proto/req-interfaces-arista-ceos b/controller/test/proto/req-interfaces-arista-ceos
old mode 100644
new mode 100755
diff --git a/controller/test/proto/req-interfaces-interface-arista-ceos b/controller/test/proto/req-interfaces-interface-arista-ceos
old mode 100644
new mode 100755
diff --git a/controller/test/proto/req-interfaces-wildcard b/controller/test/proto/req-interfaces-wildcard
old mode 100644
new mode 100755
diff --git a/controller/test/proto/resp-full-node b/controller/test/proto/resp-full-node
old mode 100644
new mode 100755
diff --git a/controller/test/proto/resp-full-node-arista-ceos b/controller/test/proto/resp-full-node-arista-ceos
old mode 100644
new mode 100755
diff --git a/controller/test/proto/resp-interfaces-arista-ceos b/controller/test/proto/resp-interfaces-arista-ceos
old mode 100644
new mode 100755
diff --git a/controller/test/proto/resp-interfaces-interface-arista-ceos b/controller/test/proto/resp-interfaces-interface-arista-ceos
old mode 100644
new mode 100755
diff --git a/controller/test/proto/resp-interfaces-wildcard b/controller/test/proto/resp-interfaces-wildcard
old mode 100644
new mode 100755
diff --git a/controller/test/proto/resp-set-system-config-hostname b/controller/test/proto/resp-set-system-config-hostname
old mode 100644
new mode 100755
diff --git a/controller/test/targets.go b/controller/test/targets.go
old mode 100644
new mode 100755
diff --git a/controller/test/terraform/.docker/ca.pem b/controller/test/terraform/.docker/ca.pem
old mode 100644
new mode 100755
diff --git a/controller/test/terraform/.docker/cert.pem b/controller/test/terraform/.docker/cert.pem
old mode 100644
new mode 100755
diff --git a/controller/test/terraform/.docker/server-cert.pem b/controller/test/terraform/.docker/server-cert.pem
old mode 100644
new mode 100755
diff --git a/controller/test/terraform/containers.tf b/controller/test/terraform/containers.tf
old mode 100644
new mode 100755
diff --git a/controller/test/terraform/images.tf b/controller/test/terraform/images.tf
old mode 100644
new mode 100755
diff --git a/controller/test/terraform/main.tf b/controller/test/terraform/main.tf
old mode 100644
new mode 100755
diff --git a/controller/test/terraform/providers.tf b/controller/test/terraform/providers.tf
old mode 100644
new mode 100755
diff --git a/controller/test/terraform/resources.tf b/controller/test/terraform/resources.tf
old mode 100644
new mode 100755
diff --git a/controller/test/terraform/variables.tf b/controller/test/terraform/variables.tf
old mode 100644
new mode 100755
diff --git a/controller/test/yang/test-module.go b/controller/test/yang/test-module.go
old mode 100644
new mode 100755
diff --git a/controller/test/yang/test.yang b/controller/test/yang/test.yang
old mode 100644
new mode 100755
diff --git a/controller/test/yang/yang.go b/controller/test/yang/yang.go
old mode 100644
new mode 100755
diff --git a/controller/topology/links/link.go b/controller/topology/links/link.go
old mode 100644
new mode 100755
diff --git a/controller/topology/nodes/databaseNodeStore.go b/controller/topology/nodes/databaseNodeStore.go
old mode 100644
new mode 100755
diff --git a/controller/topology/nodes/node.go b/controller/topology/nodes/node.go
old mode 100644
new mode 100755
diff --git a/controller/topology/nodes/nodeService.go b/controller/topology/nodes/nodeService.go
old mode 100644
new mode 100755
diff --git a/controller/topology/nodes/nodeService_test.go b/controller/topology/nodes/nodeService_test.go
old mode 100644
new mode 100755
diff --git a/controller/topology/nodes/store.go b/controller/topology/nodes/store.go
old mode 100644
new mode 100755
diff --git a/controller/topology/ports/configuration/configuration.go b/controller/topology/ports/configuration/configuration.go
old mode 100644
new mode 100755
diff --git a/controller/topology/ports/port.go b/controller/topology/ports/port.go
old mode 100644
new mode 100755
diff --git a/controller/topology/ports/portService.go b/controller/topology/ports/portService.go
old mode 100644
new mode 100755
diff --git a/controller/topology/ports/portService_test.go b/controller/topology/ports/portService_test.go
old mode 100644
new mode 100755
diff --git a/controller/topology/ports/portStore.go b/controller/topology/ports/portStore.go
old mode 100644
new mode 100755
diff --git a/controller/topology/ports/store.go b/controller/topology/ports/store.go
old mode 100644
new mode 100755
diff --git a/controller/topology/routing-tables/route.go b/controller/topology/routing-tables/route.go
old mode 100644
new mode 100755
diff --git a/controller/topology/routing-tables/routingTable.go b/controller/topology/routing-tables/routingTable.go
old mode 100644
new mode 100755
diff --git a/controller/topology/routing-tables/routingTableService.go b/controller/topology/routing-tables/routingTableService.go
old mode 100644
new mode 100755
diff --git a/controller/topology/routing-tables/routingTableService_test.go b/controller/topology/routing-tables/routingTableService_test.go
old mode 100644
new mode 100755
diff --git a/controller/topology/routing-tables/routingTableStore.go b/controller/topology/routing-tables/routingTableStore.go
old mode 100644
new mode 100755
diff --git a/controller/topology/routing-tables/store.go b/controller/topology/routing-tables/store.go
old mode 100644
new mode 100755
diff --git a/controller/topology/store.go b/controller/topology/store.go
old mode 100644
new mode 100755
diff --git a/controller/topology/store/genericStore.go b/controller/topology/store/genericStore.go
old mode 100644
new mode 100755
diff --git a/controller/topology/store/genericStore_test.go b/controller/topology/store/genericStore_test.go
old mode 100644
new mode 100755
diff --git a/controller/topology/store/query.go b/controller/topology/store/query.go
old mode 100644
new mode 100755
diff --git a/controller/topology/topology.go b/controller/topology/topology.go
old mode 100644
new mode 100755
diff --git a/controller/topology/topologyService.go b/controller/topology/topologyService.go
old mode 100644
new mode 100755
diff --git a/controller/topology/topologyService_test.go b/controller/topology/topologyService_test.go
old mode 100644
new mode 100755
diff --git a/controller/topology/topologyStore.go b/controller/topology/topologyStore.go
old mode 100644
new mode 100755
diff --git a/controller/version/version.go b/controller/version/version.go
old mode 100644
new mode 100755
diff --git a/controller/version/version_test.go b/controller/version/version_test.go
old mode 100644
new mode 100755
diff --git a/csbi/.csbi.yaml b/csbi/.csbi.yaml
old mode 100644
new mode 100755
diff --git a/csbi/Dockerfile.exec b/csbi/Dockerfile.exec
old mode 100644
new mode 100755
diff --git a/csbi/LICENSE b/csbi/LICENSE
old mode 100644
new mode 100755
diff --git a/csbi/README.md b/csbi/README.md
old mode 100644
new mode 100755
diff --git a/csbi/arista.capabilities b/csbi/arista.capabilities
old mode 100644
new mode 100755
diff --git a/csbi/build.go b/csbi/build.go
old mode 100644
new mode 100755
diff --git a/csbi/build/ci/.build-container.yml b/csbi/build/ci/.build-container.yml
old mode 100644
new mode 100755
diff --git a/csbi/build/ci/.code-quality-ci.yml b/csbi/build/ci/.code-quality-ci.yml
old mode 100644
new mode 100755
diff --git a/csbi/build/ci/.golangci-config/.golangci.yml b/csbi/build/ci/.golangci-config/.golangci.yml
old mode 100644
new mode 100755
diff --git a/csbi/build/ci/.security-and-compliance-ci.yml b/csbi/build/ci/.security-and-compliance-ci.yml
old mode 100644
new mode 100755
diff --git a/csbi/build/ci/.test.yml b/csbi/build/ci/.test.yml
old mode 100644
new mode 100755
diff --git a/csbi/build_test.go b/csbi/build_test.go
old mode 100644
new mode 100755
diff --git a/csbi/cmd/csbi/main.go b/csbi/cmd/csbi/main.go
old mode 100644
new mode 100755
diff --git a/csbi/cmd/debug/main.go b/csbi/cmd/debug/main.go
old mode 100644
new mode 100755
diff --git a/csbi/cmd/demo/main.go b/csbi/cmd/demo/main.go
old mode 100644
new mode 100755
diff --git a/csbi/cmd/deploy.go b/csbi/cmd/deploy.go
old mode 100644
new mode 100755
diff --git a/csbi/cmd/discover.go b/csbi/cmd/discover.go
old mode 100644
new mode 100755
diff --git a/csbi/cmd/executor/executor.go b/csbi/cmd/executor/executor.go
old mode 100644
new mode 100755
diff --git a/csbi/cmd/executor/experiment.yaml b/csbi/cmd/executor/experiment.yaml
old mode 100644
new mode 100755
diff --git a/csbi/cmd/generate.go b/csbi/cmd/generate.go
old mode 100644
new mode 100755
diff --git a/csbi/cmd/hello.go b/csbi/cmd/hello.go
old mode 100644
new mode 100755
diff --git a/csbi/cmd/init.go b/csbi/cmd/init.go
old mode 100644
new mode 100755
diff --git a/csbi/cmd/repository.go b/csbi/cmd/repository.go
old mode 100644
new mode 100755
diff --git a/csbi/cmd/root.go b/csbi/cmd/root.go
old mode 100644
new mode 100755
diff --git a/csbi/config/config.go b/csbi/config/config.go
old mode 100644
new mode 100755
diff --git a/csbi/csbi.Dockerfile b/csbi/csbi.Dockerfile
old mode 100644
new mode 100755
diff --git a/csbi/csbi.Dockerfile.dockerignore b/csbi/csbi.Dockerfile.dockerignore
old mode 100644
new mode 100755
diff --git a/csbi/deployment.go b/csbi/deployment.go
old mode 100644
new mode 100755
diff --git a/csbi/deployment_test.go b/csbi/deployment_test.go
old mode 100644
new mode 100755
diff --git a/csbi/discover.go b/csbi/discover.go
old mode 100644
new mode 100755
diff --git a/csbi/discover_test.go b/csbi/discover_test.go
old mode 100644
new mode 100755
diff --git a/csbi/docker-compose.yml b/csbi/docker-compose.yml
old mode 100644
new mode 100755
diff --git a/csbi/generate.go b/csbi/generate.go
old mode 100644
new mode 100755
diff --git a/csbi/generate_test.go b/csbi/generate_test.go
old mode 100644
new mode 100755
diff --git a/csbi/gnmi-target/gnmitarget.Dockerfile b/csbi/gnmi-target/gnmitarget.Dockerfile
old mode 100644
new mode 100755
diff --git a/csbi/gnmi-target/gnmitarget.Dockerfile.dockerignore b/csbi/gnmi-target/gnmitarget.Dockerfile.dockerignore
old mode 100644
new mode 100755
diff --git a/csbi/grafana/provisioning/datasources/prometheus_ds.yml b/csbi/grafana/provisioning/datasources/prometheus_ds.yml
old mode 100644
new mode 100755
diff --git a/csbi/grpc.go b/csbi/grpc.go
old mode 100644
new mode 100755
diff --git a/csbi/grpc_test.go b/csbi/grpc_test.go
old mode 100644
new mode 100755
diff --git a/csbi/http.go b/csbi/http.go
old mode 100644
new mode 100755
diff --git a/csbi/http_test.go b/csbi/http_test.go
old mode 100644
new mode 100755
diff --git a/csbi/metrics.go b/csbi/metrics.go
old mode 100644
new mode 100755
diff --git a/csbi/model.go b/csbi/model.go
old mode 100644
new mode 100755
diff --git a/csbi/orchestrator.go b/csbi/orchestrator.go
old mode 100644
new mode 100755
diff --git a/csbi/orchestrator_test.go b/csbi/orchestrator_test.go
old mode 100644
new mode 100755
diff --git a/csbi/prometheus/alerts.yml b/csbi/prometheus/alerts.yml
old mode 100644
new mode 100755
diff --git a/csbi/prometheus/prometheus.yml b/csbi/prometheus/prometheus.yml
old mode 100644
new mode 100755
diff --git a/csbi/report.xml b/csbi/report.xml
old mode 100644
new mode 100755
diff --git a/csbi/repository.go b/csbi/repository.go
old mode 100644
new mode 100755
diff --git a/csbi/repository_test.go b/csbi/repository_test.go
old mode 100644
new mode 100755
diff --git a/csbi/resources/Dockerfile b/csbi/resources/Dockerfile
old mode 100644
new mode 100755
diff --git a/csbi/resources/config.yaml b/csbi/resources/config.yaml
old mode 100644
new mode 100755
diff --git a/csbi/resources/csbi.go b/csbi/resources/csbi.go
old mode 100644
new mode 100755
diff --git a/csbi/resources/csbiAdditions.go b/csbi/resources/csbiAdditions.go
old mode 100644
new mode 100755
diff --git a/csbi/resources/go.mod b/csbi/resources/go.mod
old mode 100644
new mode 100755
diff --git a/csbi/resources/go.sum b/csbi/resources/go.sum
old mode 100644
new mode 100755
diff --git a/csbi/resources/gostructs.go b/csbi/resources/gostructs.go
old mode 100644
new mode 100755
diff --git a/csbi/run.go b/csbi/run.go
old mode 100644
new mode 100755
diff --git a/csbi/run_test.go b/csbi/run_test.go
old mode 100644
new mode 100755
diff --git a/csbi/templates.go b/csbi/templates.go
old mode 100644
new mode 100755
diff --git a/csbi/test.clab.yml b/csbi/test.clab.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/00000000-0000-0000-0000-000000000000/gostructs.go b/csbi/testdata/00000000-0000-0000-0000-000000000000/gostructs.go
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/experimental/eos/models/arista-cli.yang b/csbi/testdata/models/experimental/eos/models/arista-cli.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/experimental/eos/models/arista-eos-types.yang b/csbi/testdata/models/experimental/eos/models/arista-eos-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/experimental/eos/models/arista-exp-eos.yang b/csbi/testdata/models/experimental/eos/models/arista-exp-eos.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/experimental/eos/models/cert/arista-gnoi-cert.yang b/csbi/testdata/models/experimental/eos/models/cert/arista-gnoi-cert.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/experimental/eos/models/evpn/arista-exp-eos-evpn.yang b/csbi/testdata/models/experimental/eos/models/evpn/arista-exp-eos-evpn.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/experimental/eos/models/igmpsnooping/arista-exp-eos-igmpsnooping.yang b/csbi/testdata/models/experimental/eos/models/igmpsnooping/arista-exp-eos-igmpsnooping.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/experimental/eos/models/l2protocolforwarding/arista-exp-eos-l2protocolforwarding.yang b/csbi/testdata/models/experimental/eos/models/l2protocolforwarding/arista-exp-eos-l2protocolforwarding.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/experimental/eos/models/mlag/arista-exp-eos-mlag.yang b/csbi/testdata/models/experimental/eos/models/mlag/arista-exp-eos-mlag.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/experimental/eos/models/multicast/arista-exp-eos-multicast.yang b/csbi/testdata/models/experimental/eos/models/multicast/arista-exp-eos-multicast.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/experimental/eos/models/openconfig-component-counters.yang b/csbi/testdata/models/experimental/eos/models/openconfig-component-counters.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/experimental/eos/models/qos/arista-exp-eos-qos-acl-config.yang b/csbi/testdata/models/experimental/eos/models/qos/arista-exp-eos-qos-acl-config.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/experimental/eos/models/qos/arista-exp-eos-qos-config.yang b/csbi/testdata/models/experimental/eos/models/qos/arista-exp-eos-qos-config.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/experimental/eos/models/qos/arista-exp-eos-qos.yang b/csbi/testdata/models/experimental/eos/models/qos/arista-exp-eos-qos.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/experimental/eos/models/rpc/arista-rpc-netconf.yang b/csbi/testdata/models/experimental/eos/models/rpc/arista-rpc-netconf.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/experimental/eos/models/varp/arista-exp-eos-varp-intf.yang b/csbi/testdata/models/experimental/eos/models/varp/arista-exp-eos-varp-intf.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/experimental/eos/models/varp/arista-exp-eos-varp-net-inst.yang b/csbi/testdata/models/experimental/eos/models/varp/arista-exp-eos-varp-net-inst.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/experimental/eos/models/vlan/vlan-translation.yang b/csbi/testdata/models/experimental/eos/models/vlan/vlan-translation.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/experimental/eos/models/vxlan/arista-exp-eos-vxlan-config.yang b/csbi/testdata/models/experimental/eos/models/vxlan/arista-exp-eos-vxlan-config.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/experimental/eos/models/vxlan/arista-exp-eos-vxlan.yang b/csbi/testdata/models/experimental/eos/models/vxlan/arista-exp-eos-vxlan.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/hercules/LICENSE b/csbi/testdata/models/openconfig/hercules/LICENSE
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules-interfaces.yang b/csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules-interfaces.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules-platform-chassis.yang b/csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules-platform-chassis.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules-platform-linecard.yang b/csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules-platform-linecard.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules-platform-node.yang b/csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules-platform-node.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules-platform-port.yang b/csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules-platform-port.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules-platform.yang b/csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules-platform.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules-qos.yang b/csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules-qos.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules.yang b/csbi/testdata/models/openconfig/hercules/yang/openconfig-hercules.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/LICENSE b/csbi/testdata/models/openconfig/public/LICENSE
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/README.md b/csbi/testdata/models/openconfig/public/release/README.md
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/acl/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/acl/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/acl/openconfig-acl.yang b/csbi/testdata/models/openconfig/public/release/models/acl/openconfig-acl.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/acl/openconfig-packet-match-types.yang b/csbi/testdata/models/openconfig/public/release/models/acl/openconfig-packet-match-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/acl/openconfig-packet-match.yang b/csbi/testdata/models/openconfig/public/release/models/acl/openconfig-packet-match.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/aft/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/aft/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-common.yang b/csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-common.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-ethernet.yang b/csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-ethernet.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-ipv4.yang b/csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-ipv4.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-ipv6.yang b/csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-ipv6.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-mpls.yang b/csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-mpls.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-network-instance.yang b/csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-network-instance.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-pf.yang b/csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-pf.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-types.yang b/csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft.yang b/csbi/testdata/models/openconfig/public/release/models/aft/openconfig-aft.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/bfd/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/bfd/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/bfd/openconfig-bfd.yang b/csbi/testdata/models/openconfig/public/release/models/bfd/openconfig-bfd.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/bgp/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/bgp/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-common-multiprotocol.yang b/csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-common-multiprotocol.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-common-structure.yang b/csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-common-structure.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-common.yang b/csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-common.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-errors.yang b/csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-errors.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-global.yang b/csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-global.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-neighbor.yang b/csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-neighbor.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-peer-group.yang b/csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-peer-group.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-policy.yang b/csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-policy.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-types.yang b/csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp.yang b/csbi/testdata/models/openconfig/public/release/models/bgp/openconfig-bgp.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/catalog/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/catalog/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/catalog/openconfig-catalog-types.yang b/csbi/testdata/models/openconfig/public/release/models/catalog/openconfig-catalog-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/catalog/openconfig-module-catalog.yang b/csbi/testdata/models/openconfig/public/release/models/catalog/openconfig-module-catalog.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/firewall/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/firewall/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/firewall/openconfig-fw-high-availability.yang b/csbi/testdata/models/openconfig/public/release/models/firewall/openconfig-fw-high-availability.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/firewall/openconfig-fw-link-monitoring.yang b/csbi/testdata/models/openconfig/public/release/models/firewall/openconfig-fw-link-monitoring.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/interfaces/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/interfaces/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-8021x.yang b/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-8021x.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-aggregate.yang b/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-aggregate.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-ethernet-ext.yang b/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-ethernet-ext.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-ethernet.yang b/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-ethernet.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-ip-ext.yang b/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-ip-ext.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-ip.yang b/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-ip.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-poe.yang b/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-poe.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-sdn-ext.yang b/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-sdn-ext.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-tunnel.yang b/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-tunnel.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-types.yang b/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-if-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-interfaces.yang b/csbi/testdata/models/openconfig/public/release/models/interfaces/openconfig-interfaces.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/isis/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/isis/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/isis/openconfig-isis-lsdb-types.yang b/csbi/testdata/models/openconfig/public/release/models/isis/openconfig-isis-lsdb-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/isis/openconfig-isis-lsp.yang b/csbi/testdata/models/openconfig/public/release/models/isis/openconfig-isis-lsp.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/isis/openconfig-isis-policy.yang b/csbi/testdata/models/openconfig/public/release/models/isis/openconfig-isis-policy.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/isis/openconfig-isis-routing.yang b/csbi/testdata/models/openconfig/public/release/models/isis/openconfig-isis-routing.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/isis/openconfig-isis-types.yang b/csbi/testdata/models/openconfig/public/release/models/isis/openconfig-isis-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/isis/openconfig-isis.yang b/csbi/testdata/models/openconfig/public/release/models/isis/openconfig-isis.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/lacp/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/lacp/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/lacp/openconfig-lacp.yang b/csbi/testdata/models/openconfig/public/release/models/lacp/openconfig-lacp.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/lldp/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/lldp/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/lldp/openconfig-lldp-types.yang b/csbi/testdata/models/openconfig/public/release/models/lldp/openconfig-lldp-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/lldp/openconfig-lldp.yang b/csbi/testdata/models/openconfig/public/release/models/lldp/openconfig-lldp.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/local-routing/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/local-routing/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/local-routing/openconfig-local-routing.yang b/csbi/testdata/models/openconfig/public/release/models/local-routing/openconfig-local-routing.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/macsec/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/macsec/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/macsec/openconfig-macsec-types.yang b/csbi/testdata/models/openconfig/public/release/models/macsec/openconfig-macsec-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/macsec/openconfig-macsec.yang b/csbi/testdata/models/openconfig/public/release/models/macsec/openconfig-macsec.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/mpls/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/mpls/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls-igp.yang b/csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls-igp.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls-ldp.yang b/csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls-ldp.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls-rsvp.yang b/csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls-rsvp.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls-sr.yang b/csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls-sr.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls-static.yang b/csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls-static.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls-te.yang b/csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls-te.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls-types.yang b/csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls.yang b/csbi/testdata/models/openconfig/public/release/models/mpls/openconfig-mpls.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/multicast/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/multicast/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/multicast/openconfig-igmp-types.yang b/csbi/testdata/models/openconfig/public/release/models/multicast/openconfig-igmp-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/multicast/openconfig-igmp.yang b/csbi/testdata/models/openconfig/public/release/models/multicast/openconfig-igmp.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/multicast/openconfig-pim-types.yang b/csbi/testdata/models/openconfig/public/release/models/multicast/openconfig-pim-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/multicast/openconfig-pim.yang b/csbi/testdata/models/openconfig/public/release/models/multicast/openconfig-pim.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/network-instance/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/network-instance/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/network-instance/openconfig-network-instance-l2.yang b/csbi/testdata/models/openconfig/public/release/models/network-instance/openconfig-network-instance-l2.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/network-instance/openconfig-network-instance-l3.yang b/csbi/testdata/models/openconfig/public/release/models/network-instance/openconfig-network-instance-l3.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/network-instance/openconfig-network-instance-policy.yang b/csbi/testdata/models/openconfig/public/release/models/network-instance/openconfig-network-instance-policy.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/network-instance/openconfig-network-instance-types.yang b/csbi/testdata/models/openconfig/public/release/models/network-instance/openconfig-network-instance-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/network-instance/openconfig-network-instance.yang b/csbi/testdata/models/openconfig/public/release/models/network-instance/openconfig-network-instance.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/openconfig-extensions.yang b/csbi/testdata/models/openconfig/public/release/models/openconfig-extensions.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/openflow/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/openflow/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/openflow/openconfig-openflow-types.yang b/csbi/testdata/models/openconfig/public/release/models/openflow/openconfig-openflow-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/openflow/openconfig-openflow.yang b/csbi/testdata/models/openconfig/public/release/models/openflow/openconfig-openflow.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/optical-transport/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/optical-transport/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-channel-monitor.yang b/csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-channel-monitor.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-optical-amplifier.yang b/csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-optical-amplifier.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-optical-attenuator.yang b/csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-optical-attenuator.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-terminal-device.yang b/csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-terminal-device.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-transport-line-common.yang b/csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-transport-line-common.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-transport-line-connectivity.yang b/csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-transport-line-connectivity.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-transport-line-protection.yang b/csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-transport-line-protection.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-transport-types.yang b/csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-transport-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-wavelength-router.yang b/csbi/testdata/models/openconfig/public/release/models/optical-transport/openconfig-wavelength-router.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/ospf/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/ospf/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospf-policy.yang b/csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospf-policy.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospf-types.yang b/csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospf-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospfv2-area-interface.yang b/csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospfv2-area-interface.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospfv2-area.yang b/csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospfv2-area.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospfv2-common.yang b/csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospfv2-common.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospfv2-global.yang b/csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospfv2-global.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospfv2-lsdb.yang b/csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospfv2-lsdb.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospfv2.yang b/csbi/testdata/models/openconfig/public/release/models/ospf/openconfig-ospfv2.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/p4rt/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/p4rt/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/p4rt/openconfig-p4rt.yang b/csbi/testdata/models/openconfig/public/release/models/p4rt/openconfig-p4rt.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/platform/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/platform/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-cpu.yang b/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-cpu.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-ext.yang b/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-ext.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-fan.yang b/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-fan.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-linecard.yang b/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-linecard.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-pipeline-counters.yang b/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-pipeline-counters.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-port.yang b/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-port.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-psu.yang b/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-psu.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-software.yang b/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-software.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-transceiver.yang b/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-transceiver.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-types.yang b/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform.yang b/csbi/testdata/models/openconfig/public/release/models/platform/openconfig-platform.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/policy-forwarding/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/policy-forwarding/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/policy-forwarding/openconfig-pf-forwarding-policies.yang b/csbi/testdata/models/openconfig/public/release/models/policy-forwarding/openconfig-pf-forwarding-policies.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/policy-forwarding/openconfig-pf-interfaces.yang b/csbi/testdata/models/openconfig/public/release/models/policy-forwarding/openconfig-pf-interfaces.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/policy-forwarding/openconfig-pf-path-groups.yang b/csbi/testdata/models/openconfig/public/release/models/policy-forwarding/openconfig-pf-path-groups.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/policy-forwarding/openconfig-pf-srte.yang b/csbi/testdata/models/openconfig/public/release/models/policy-forwarding/openconfig-pf-srte.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/policy-forwarding/openconfig-policy-forwarding.yang b/csbi/testdata/models/openconfig/public/release/models/policy-forwarding/openconfig-policy-forwarding.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/policy/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/policy/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/policy/openconfig-policy-types.yang b/csbi/testdata/models/openconfig/public/release/models/policy/openconfig-policy-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/policy/openconfig-routing-policy.yang b/csbi/testdata/models/openconfig/public/release/models/policy/openconfig-routing-policy.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/probes/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/probes/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/probes/openconfig-probes-types.yang b/csbi/testdata/models/openconfig/public/release/models/probes/openconfig-probes-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/probes/openconfig-probes.yang b/csbi/testdata/models/openconfig/public/release/models/probes/openconfig-probes.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/qos/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/qos/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/qos/openconfig-qos-elements.yang b/csbi/testdata/models/openconfig/public/release/models/qos/openconfig-qos-elements.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/qos/openconfig-qos-interfaces.yang b/csbi/testdata/models/openconfig/public/release/models/qos/openconfig-qos-interfaces.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/qos/openconfig-qos-types.yang b/csbi/testdata/models/openconfig/public/release/models/qos/openconfig-qos-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/qos/openconfig-qos.yang b/csbi/testdata/models/openconfig/public/release/models/qos/openconfig-qos.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/relay-agent/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/relay-agent/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/relay-agent/openconfig-relay-agent.yang b/csbi/testdata/models/openconfig/public/release/models/relay-agent/openconfig-relay-agent.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/rib/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/rib/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/rib/openconfig-rib-bgp-attributes.yang b/csbi/testdata/models/openconfig/public/release/models/rib/openconfig-rib-bgp-attributes.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/rib/openconfig-rib-bgp-ext.yang b/csbi/testdata/models/openconfig/public/release/models/rib/openconfig-rib-bgp-ext.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/rib/openconfig-rib-bgp-shared-attributes.yang b/csbi/testdata/models/openconfig/public/release/models/rib/openconfig-rib-bgp-shared-attributes.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/rib/openconfig-rib-bgp-table-attributes.yang b/csbi/testdata/models/openconfig/public/release/models/rib/openconfig-rib-bgp-table-attributes.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/rib/openconfig-rib-bgp-tables.yang b/csbi/testdata/models/openconfig/public/release/models/rib/openconfig-rib-bgp-tables.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/rib/openconfig-rib-bgp-types.yang b/csbi/testdata/models/openconfig/public/release/models/rib/openconfig-rib-bgp-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/rib/openconfig-rib-bgp.yang b/csbi/testdata/models/openconfig/public/release/models/rib/openconfig-rib-bgp.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/sampling/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/sampling/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/sampling/openconfig-sampling-sflow.yang b/csbi/testdata/models/openconfig/public/release/models/sampling/openconfig-sampling-sflow.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/segment-routing/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/segment-routing/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/segment-routing/openconfig-rsvp-sr-ext.yang b/csbi/testdata/models/openconfig/public/release/models/segment-routing/openconfig-rsvp-sr-ext.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/segment-routing/openconfig-segment-routing-types.yang b/csbi/testdata/models/openconfig/public/release/models/segment-routing/openconfig-segment-routing-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/segment-routing/openconfig-segment-routing.yang b/csbi/testdata/models/openconfig/public/release/models/segment-routing/openconfig-segment-routing.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/segment-routing/openconfig-srte-policy.yang b/csbi/testdata/models/openconfig/public/release/models/segment-routing/openconfig-srte-policy.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/stp/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/stp/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/stp/openconfig-spanning-tree-types.yang b/csbi/testdata/models/openconfig/public/release/models/stp/openconfig-spanning-tree-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/stp/openconfig-spanning-tree.yang b/csbi/testdata/models/openconfig/public/release/models/stp/openconfig-spanning-tree.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/system/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/system/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/system/openconfig-aaa-radius.yang b/csbi/testdata/models/openconfig/public/release/models/system/openconfig-aaa-radius.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/system/openconfig-aaa-tacacs.yang b/csbi/testdata/models/openconfig/public/release/models/system/openconfig-aaa-tacacs.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/system/openconfig-aaa-types.yang b/csbi/testdata/models/openconfig/public/release/models/system/openconfig-aaa-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/system/openconfig-aaa.yang b/csbi/testdata/models/openconfig/public/release/models/system/openconfig-aaa.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/system/openconfig-alarm-types.yang b/csbi/testdata/models/openconfig/public/release/models/system/openconfig-alarm-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/system/openconfig-alarms.yang b/csbi/testdata/models/openconfig/public/release/models/system/openconfig-alarms.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/system/openconfig-license.yang b/csbi/testdata/models/openconfig/public/release/models/system/openconfig-license.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/system/openconfig-messages.yang b/csbi/testdata/models/openconfig/public/release/models/system/openconfig-messages.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/system/openconfig-procmon.yang b/csbi/testdata/models/openconfig/public/release/models/system/openconfig-procmon.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/system/openconfig-system-logging.yang b/csbi/testdata/models/openconfig/public/release/models/system/openconfig-system-logging.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/system/openconfig-system-management.yang b/csbi/testdata/models/openconfig/public/release/models/system/openconfig-system-management.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/system/openconfig-system-terminal.yang b/csbi/testdata/models/openconfig/public/release/models/system/openconfig-system-terminal.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/system/openconfig-system.yang b/csbi/testdata/models/openconfig/public/release/models/system/openconfig-system.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/telemetry/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/telemetry/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/telemetry/openconfig-telemetry-types.yang b/csbi/testdata/models/openconfig/public/release/models/telemetry/openconfig-telemetry-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/telemetry/openconfig-telemetry.yang b/csbi/testdata/models/openconfig/public/release/models/telemetry/openconfig-telemetry.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/types/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/types/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/types/openconfig-inet-types.yang b/csbi/testdata/models/openconfig/public/release/models/types/openconfig-inet-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/types/openconfig-types.yang b/csbi/testdata/models/openconfig/public/release/models/types/openconfig-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/types/openconfig-yang-types.yang b/csbi/testdata/models/openconfig/public/release/models/types/openconfig-yang-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/vlan/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/vlan/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/vlan/openconfig-vlan-types.yang b/csbi/testdata/models/openconfig/public/release/models/vlan/openconfig-vlan-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/vlan/openconfig-vlan.yang b/csbi/testdata/models/openconfig/public/release/models/vlan/openconfig-vlan.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/wifi/.spec.yml b/csbi/testdata/models/openconfig/public/release/models/wifi/.spec.yml
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/wifi/README.md b/csbi/testdata/models/openconfig/public/release/models/wifi/README.md
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/wifi/openconfig-access-points.yang b/csbi/testdata/models/openconfig/public/release/models/wifi/openconfig-access-points.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/wifi/openconfig-ap-interfaces.yang b/csbi/testdata/models/openconfig/public/release/models/wifi/openconfig-ap-interfaces.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/wifi/openconfig-ap-manager.yang b/csbi/testdata/models/openconfig/public/release/models/wifi/openconfig-ap-manager.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/wifi/openconfig-wifi-mac.yang b/csbi/testdata/models/openconfig/public/release/models/wifi/openconfig-wifi-mac.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/wifi/openconfig-wifi-phy.yang b/csbi/testdata/models/openconfig/public/release/models/wifi/openconfig-wifi-phy.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/openconfig/public/release/models/wifi/openconfig-wifi-types.yang b/csbi/testdata/models/openconfig/public/release/models/wifi/openconfig-wifi-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/acl/arista-acl-deviations.yang b/csbi/testdata/models/release/openconfig/models/acl/arista-acl-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/aft/arista-aft-augments.yang b/csbi/testdata/models/release/openconfig/models/aft/arista-aft-augments.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/bfd/arista-bfd-augments.yang b/csbi/testdata/models/release/openconfig/models/bfd/arista-bfd-augments.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/bfd/arista-bfd-deviations.yang b/csbi/testdata/models/release/openconfig/models/bfd/arista-bfd-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/bgp/arista-bgp-augments.yang b/csbi/testdata/models/release/openconfig/models/bgp/arista-bgp-augments.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/bgp/arista-bgp-deviations.yang b/csbi/testdata/models/release/openconfig/models/bgp/arista-bgp-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/interfaces/arista-intf-augments.yang b/csbi/testdata/models/release/openconfig/models/interfaces/arista-intf-augments.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/interfaces/arista-intf-deviations.yang b/csbi/testdata/models/release/openconfig/models/interfaces/arista-intf-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/isis/arista-isis-augments.yang b/csbi/testdata/models/release/openconfig/models/isis/arista-isis-augments.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/isis/arista-isis-deviations.yang b/csbi/testdata/models/release/openconfig/models/isis/arista-isis-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/lacp/arista-lacp-augments.yang b/csbi/testdata/models/release/openconfig/models/lacp/arista-lacp-augments.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/lacp/arista-lacp-deviations.yang b/csbi/testdata/models/release/openconfig/models/lacp/arista-lacp-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/lldp/arista-lldp-augments.yang b/csbi/testdata/models/release/openconfig/models/lldp/arista-lldp-augments.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/lldp/arista-lldp-deviations.yang b/csbi/testdata/models/release/openconfig/models/lldp/arista-lldp-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/local-routing/arista-local-routing-deviations.yang b/csbi/testdata/models/release/openconfig/models/local-routing/arista-local-routing-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/mpls/arista-mpls-augments.yang b/csbi/testdata/models/release/openconfig/models/mpls/arista-mpls-augments.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/mpls/arista-mpls-deviations.yang b/csbi/testdata/models/release/openconfig/models/mpls/arista-mpls-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/multicast/arista-pim-augments.yang b/csbi/testdata/models/release/openconfig/models/multicast/arista-pim-augments.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/network-instance/arista-netinst-deviations.yang b/csbi/testdata/models/release/openconfig/models/network-instance/arista-netinst-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/network-instance/arista-vlan-augments.yang b/csbi/testdata/models/release/openconfig/models/network-instance/arista-vlan-augments.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/network-instance/arista-vlan-deviations.yang b/csbi/testdata/models/release/openconfig/models/network-instance/arista-vlan-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/not-supported/arista-acl-notsupported-deviations.yang b/csbi/testdata/models/release/openconfig/models/not-supported/arista-acl-notsupported-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/not-supported/arista-bfd-notsupported-deviations.yang b/csbi/testdata/models/release/openconfig/models/not-supported/arista-bfd-notsupported-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/not-supported/arista-bgp-notsupported-deviations.yang b/csbi/testdata/models/release/openconfig/models/not-supported/arista-bgp-notsupported-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/not-supported/arista-interfaces-notsupported-deviations.yang b/csbi/testdata/models/release/openconfig/models/not-supported/arista-interfaces-notsupported-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/not-supported/arista-lacp-notsupported-deviations.yang b/csbi/testdata/models/release/openconfig/models/not-supported/arista-lacp-notsupported-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/not-supported/arista-lldp-notsupported-deviations.yang b/csbi/testdata/models/release/openconfig/models/not-supported/arista-lldp-notsupported-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/not-supported/arista-local-routing-notsupported-deviations.yang b/csbi/testdata/models/release/openconfig/models/not-supported/arista-local-routing-notsupported-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/not-supported/arista-messages-notsupported-deviations.yang b/csbi/testdata/models/release/openconfig/models/not-supported/arista-messages-notsupported-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/not-supported/arista-network-instance-notsupported-deviations.yang b/csbi/testdata/models/release/openconfig/models/not-supported/arista-network-instance-notsupported-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/not-supported/arista-platform-notsupported-deviations.yang b/csbi/testdata/models/release/openconfig/models/not-supported/arista-platform-notsupported-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/not-supported/arista-qos-notsupported-deviations.yang b/csbi/testdata/models/release/openconfig/models/not-supported/arista-qos-notsupported-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/not-supported/arista-routing-policy-notsupported-deviations.yang b/csbi/testdata/models/release/openconfig/models/not-supported/arista-routing-policy-notsupported-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/not-supported/arista-system-notsupported-deviations.yang b/csbi/testdata/models/release/openconfig/models/not-supported/arista-system-notsupported-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/openflow/arista-openflow-deviations.yang b/csbi/testdata/models/release/openconfig/models/openflow/arista-openflow-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/policy-forwarding/arista-srte-augments.yang b/csbi/testdata/models/release/openconfig/models/policy-forwarding/arista-srte-augments.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/policy-forwarding/arista-srte-deviations.yang b/csbi/testdata/models/release/openconfig/models/policy-forwarding/arista-srte-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/policy/arista-rpol-augments.yang b/csbi/testdata/models/release/openconfig/models/policy/arista-rpol-augments.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/policy/arista-rpol-deviations.yang b/csbi/testdata/models/release/openconfig/models/policy/arista-rpol-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/qos/arista-qos-augments.yang b/csbi/testdata/models/release/openconfig/models/qos/arista-qos-augments.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/relay-agent/arista-relay-agent-deviations.yang b/csbi/testdata/models/release/openconfig/models/relay-agent/arista-relay-agent-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/system/arista-system-augments.yang b/csbi/testdata/models/release/openconfig/models/system/arista-system-augments.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/release/openconfig/models/system/arista-system-deviations.yang b/csbi/testdata/models/release/openconfig/models/system/arista-system-deviations.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/third_party/README.md b/csbi/testdata/models/third_party/README.md
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/third_party/ietf/iana-if-type.yang b/csbi/testdata/models/third_party/ietf/iana-if-type.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/third_party/ietf/ietf-inet-types.yang b/csbi/testdata/models/third_party/ietf/ietf-inet-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/third_party/ietf/ietf-interfaces.yang b/csbi/testdata/models/third_party/ietf/ietf-interfaces.yang
old mode 100644
new mode 100755
diff --git a/csbi/testdata/models/third_party/ietf/ietf-yang-types.yang b/csbi/testdata/models/third_party/ietf/ietf-yang-types.yang
old mode 100644
new mode 100755
diff --git a/csbi/write.go b/csbi/write.go
old mode 100644
new mode 100755
diff --git a/csbi/write_test.go b/csbi/write_test.go
old mode 100644
new mode 100755
diff --git a/dev_env_data/clab/basic_one_arista.yaml b/dev_env_data/clab/basic_one_arista.yaml
old mode 100644
new mode 100755
diff --git a/dev_env_data/clab/basic_two_aristas.yaml b/dev_env_data/clab/basic_two_aristas.yaml
old mode 100644
new mode 100755
diff --git a/dev_env_data/clab/basic_two_gnmi_targets.yaml b/dev_env_data/clab/basic_two_gnmi_targets.yaml
old mode 100644
new mode 100755
diff --git a/dev_env_data/clab/demo.clab.yaml b/dev_env_data/clab/demo.clab.yaml
old mode 100644
new mode 100755
diff --git a/dev_env_data/clab/gosdn.clab.yaml b/dev_env_data/clab/gosdn.clab.yaml
old mode 100644
new mode 100755
diff --git a/dev_env_data/clab/gosdn_slim.clab.yaml b/dev_env_data/clab/gosdn_slim.clab.yaml
old mode 100644
new mode 100755
diff --git a/dev_env_data/docker-compose/basic_docker-compose.yml b/dev_env_data/docker-compose/basic_docker-compose.yml
old mode 100644
new mode 100755
diff --git a/dev_env_data/docker-compose/integration-test_docker-compose.yml b/dev_env_data/docker-compose/integration-test_docker-compose.yml
old mode 100644
new mode 100755
diff --git a/dev_env_data/plugin-registry/plugin-store.json b/dev_env_data/plugin-registry/plugin-store.json
old mode 100644
new mode 100755
diff --git a/dev_env_data/sdn/basic_two_aristas.json b/dev_env_data/sdn/basic_two_aristas.json
old mode 100644
new mode 100755
diff --git a/docker-compose.yml b/docker-compose.yml
old mode 100644
new mode 100755
diff --git a/docker_volume_backup/.gitkeep b/docker_volume_backup/.gitkeep
old mode 100644
new mode 100755
diff --git a/docs/images/logo.png b/docs/images/logo.png
old mode 100644
new mode 100755
diff --git a/docs/images/logo.svg b/docs/images/logo.svg
old mode 100644
new mode 100755
diff --git a/docs/index.md b/docs/index.md
old mode 100644
new mode 100755
diff --git a/documentation/README.md b/documentation/README.md
old mode 100644
new mode 100755
diff --git a/documentation/SUMMARY.md b/documentation/SUMMARY.md
old mode 100644
new mode 100755
diff --git a/documentation/figures/.gitkeep b/documentation/figures/.gitkeep
old mode 100644
new mode 100755
diff --git a/documentation/figures/nucleus/.gitkeep b/documentation/figures/nucleus/.gitkeep
old mode 100644
new mode 100755
diff --git a/documentation/figures/nucleus/updated_controller_architecture_nucleus.drawio b/documentation/figures/nucleus/updated_controller_architecture_nucleus.drawio
old mode 100644
new mode 100755
diff --git a/documentation/figures/nucleus/updated_controller_architecture_nucleus.drawio.png b/documentation/figures/nucleus/updated_controller_architecture_nucleus.drawio.png
old mode 100644
new mode 100755
diff --git a/documentation/figures/overview/.gitkeep b/documentation/figures/overview/.gitkeep
old mode 100644
new mode 100755
diff --git a/documentation/figures/overview/updated_controller_architecture_overview.drawio b/documentation/figures/overview/updated_controller_architecture_overview.drawio
old mode 100644
new mode 100755
diff --git a/documentation/figures/overview/updated_controller_architecture_overview.drawio.png b/documentation/figures/overview/updated_controller_architecture_overview.drawio.png
old mode 100644
new mode 100755
diff --git a/documentation/figures/plugins/.gitkeep b/documentation/figures/plugins/.gitkeep
old mode 100644
new mode 100755
diff --git a/documentation/figures/plugins/plugin-device-interaction.drawio b/documentation/figures/plugins/plugin-device-interaction.drawio
old mode 100644
new mode 100755
diff --git a/documentation/figures/plugins/plugin-device-interaction.drawio.png b/documentation/figures/plugins/plugin-device-interaction.drawio.png
old mode 100644
new mode 100755
diff --git a/forks/LICENSE b/forks/LICENSE
old mode 100644
new mode 100755
diff --git a/forks/README.md b/forks/README.md
old mode 100644
new mode 100755
diff --git a/forks/goarista/gnmi/arbitration.go b/forks/goarista/gnmi/arbitration.go
old mode 100644
new mode 100755
diff --git a/forks/goarista/gnmi/arbitration_test.go b/forks/goarista/gnmi/arbitration_test.go
old mode 100644
new mode 100755
diff --git a/forks/goarista/gnmi/client.go b/forks/goarista/gnmi/client.go
old mode 100644
new mode 100755
diff --git a/forks/goarista/gnmi/json.go b/forks/goarista/gnmi/json.go
old mode 100644
new mode 100755
diff --git a/forks/goarista/gnmi/operation.go b/forks/goarista/gnmi/operation.go
old mode 100644
new mode 100755
diff --git a/forks/goarista/gnmi/operation_test.go b/forks/goarista/gnmi/operation_test.go
old mode 100644
new mode 100755
diff --git a/forks/goarista/gnmi/path.go b/forks/goarista/gnmi/path.go
old mode 100644
new mode 100755
diff --git a/forks/goarista/gnmi/path_test.go b/forks/goarista/gnmi/path_test.go
old mode 100644
new mode 100755
diff --git a/forks/google/README.md b/forks/google/README.md
old mode 100644
new mode 100755
diff --git a/forks/google/gnmi/model.go b/forks/google/gnmi/model.go
old mode 100644
new mode 100755
diff --git a/forks/google/gnmi/modeldata/gostruct/gen.go b/forks/google/gnmi/modeldata/gostruct/gen.go
old mode 100644
new mode 100755
diff --git a/forks/google/gnmi/modeldata/gostruct/generated.go.wasd b/forks/google/gnmi/modeldata/gostruct/generated.go.wasd
old mode 100644
new mode 100755
diff --git a/forks/google/gnmi/modeldata/modeldata.go b/forks/google/gnmi/modeldata/modeldata.go
old mode 100644
new mode 100755
diff --git a/forks/google/gnmi/server.go b/forks/google/gnmi/server.go
old mode 100644
new mode 100755
diff --git a/forks/google/gnmi/server_test.go.wasd b/forks/google/gnmi/server_test.go.wasd
old mode 100644
new mode 100755
diff --git a/forks/google/gnmi/util.go b/forks/google/gnmi/util.go
old mode 100644
new mode 100755
diff --git a/go.mod b/go.mod
old mode 100644
new mode 100755
diff --git a/go.sum b/go.sum
old mode 100644
new mode 100755
diff --git a/gosdn-cli-showcase.webm b/gosdn-cli-showcase.webm
old mode 100644
new mode 100755
diff --git a/integration-tests/application_tests/appUtility_test.go b/integration-tests/application_tests/appUtility_test.go
old mode 100644
new mode 100755
diff --git a/integration-tests/application_tests/application_test.go b/integration-tests/application_tests/application_test.go
old mode 100644
new mode 100755
diff --git a/integration-tests/application_tests/eventAssertion_test.go b/integration-tests/application_tests/eventAssertion_test.go
old mode 100644
new mode 100755
diff --git a/integration-tests/example_tests/example_test.go b/integration-tests/example_tests/example_test.go
old mode 100644
new mode 100755
diff --git a/integration-tests/integrationTestUtils/integrationTestUtils.go b/integration-tests/integrationTestUtils/integrationTestUtils.go
old mode 100644
new mode 100755
diff --git a/integration-tests/lab_tests/lab00_test.go b/integration-tests/lab_tests/lab00_test.go
old mode 100644
new mode 100755
diff --git a/integration-tests/lab_tests/labUtility_test.go b/integration-tests/lab_tests/labUtility_test.go
old mode 100644
new mode 100755
diff --git a/integration-tests/networkElement_tests/modelUtility_test.go b/integration-tests/networkElement_tests/modelUtility_test.go
old mode 100644
new mode 100755
diff --git a/integration-tests/networkElement_tests/networkElement_test.go b/integration-tests/networkElement_tests/networkElement_test.go
old mode 100644
new mode 100755
diff --git a/integration-tests/rbac_tests/rbac_test.go b/integration-tests/rbac_tests/rbac_test.go
old mode 100644
new mode 100755
diff --git a/integration-tests/topology_tests/topology_test.go b/integration-tests/topology_tests/topology_test.go
old mode 100644
new mode 100755
diff --git a/lab-vm/README.md b/lab-vm/README.md
old mode 100644
new mode 100755
diff --git a/lab-vm/vm-with-packer/gosdn_vm.pkr.hcl b/lab-vm/vm-with-packer/gosdn_vm.pkr.hcl
old mode 100644
new mode 100755
diff --git a/lab-vm/vm-with-packer/http/meta-data b/lab-vm/vm-with-packer/http/meta-data
old mode 100644
new mode 100755
diff --git a/lab-vm/vm-with-packer/http/user-data b/lab-vm/vm-with-packer/http/user-data
old mode 100644
new mode 100755
diff --git a/lab-vm/vm-with-packer/scripts/gosdn_clone.sh b/lab-vm/vm-with-packer/scripts/gosdn_clone.sh
old mode 100644
new mode 100755
diff --git a/lab-vm/vm-with-packer/scripts/setup.sh b/lab-vm/vm-with-packer/scripts/setup.sh
old mode 100644
new mode 100755
diff --git a/lab-vm/vm-with-vagrant/Vagrantfile b/lab-vm/vm-with-vagrant/Vagrantfile
old mode 100644
new mode 100755
diff --git a/makefiles/build/Makefile b/makefiles/build/Makefile
old mode 100644
new mode 100755
diff --git a/makefiles/ci/Makefile b/makefiles/ci/Makefile
old mode 100644
new mode 100755
diff --git a/makefiles/clab/Makefile b/makefiles/clab/Makefile
old mode 100644
new mode 100755
diff --git a/makefiles/container/Makefile b/makefiles/container/Makefile
old mode 100644
new mode 100755
diff --git a/makefiles/generate/Makefile b/makefiles/generate/Makefile
old mode 100644
new mode 100755
diff --git a/mkdocs.yml b/mkdocs.yml
old mode 100644
new mode 100755
diff --git a/models/generated/README.md b/models/generated/README.md
old mode 100644
new mode 100755
diff --git a/models/generated/arista/additions.patch b/models/generated/arista/additions.patch
old mode 100644
new mode 100755
diff --git a/models/generated/arista/arista.go b/models/generated/arista/arista.go
old mode 100644
new mode 100755
diff --git a/models/generated/arista/config.yaml b/models/generated/arista/config.yaml
old mode 100644
new mode 100755
diff --git a/models/generated/arista/yang.go b/models/generated/arista/yang.go
old mode 100644
new mode 100755
diff --git a/models/generated/openconfig/additions.patch b/models/generated/openconfig/additions.patch
old mode 100644
new mode 100755
diff --git a/models/generated/openconfig/config.yaml b/models/generated/openconfig/config.yaml
old mode 100644
new mode 100755
diff --git a/models/generated/openconfig/openconfig.go b/models/generated/openconfig/openconfig.go
old mode 100644
new mode 100755
diff --git a/models/generated/openconfig/yang.go b/models/generated/openconfig/yang.go
old mode 100644
new mode 100755
diff --git a/plugin-registry/README.md b/plugin-registry/README.md
old mode 100644
new mode 100755
diff --git a/plugin-registry/main.go b/plugin-registry/main.go
old mode 100644
new mode 100755
diff --git a/plugin-registry/plugin-registry.Dockerfile b/plugin-registry/plugin-registry.Dockerfile
old mode 100644
new mode 100755
diff --git a/plugin-registry/plugin-registry.Dockerfile.dockerignore b/plugin-registry/plugin-registry.Dockerfile.dockerignore
old mode 100644
new mode 100755
diff --git a/plugin-registry/plugin-registry.debug.Dockerfile b/plugin-registry/plugin-registry.debug.Dockerfile
old mode 100644
new mode 100755
diff --git a/plugin-registry/plugin-registry.debug.Dockerfile.dockerignore b/plugin-registry/plugin-registry.debug.Dockerfile.dockerignore
old mode 100644
new mode 100755
diff --git a/plugin-registry/registry.go b/plugin-registry/registry.go
old mode 100644
new mode 100755
diff --git a/plugin-registry/server.go b/plugin-registry/server.go
old mode 100644
new mode 100755
diff --git a/plugin-registry/store.go b/plugin-registry/store.go
old mode 100644
new mode 100755
diff --git a/plugins/README.md b/plugins/README.md
old mode 100644
new mode 100755
diff --git a/plugins/examples/arista/cmd/main.go b/plugins/examples/arista/cmd/main.go
old mode 100644
new mode 100755
diff --git a/plugins/examples/arista/plugin.yaml b/plugins/examples/arista/plugin.yaml
old mode 100644
new mode 100755
diff --git a/plugins/examples/openconfig/cmd/main.go b/plugins/examples/openconfig/cmd/main.go
old mode 100644
new mode 100755
diff --git a/plugins/examples/openconfig/plugin.yaml b/plugins/examples/openconfig/plugin.yaml
old mode 100644
new mode 100755
diff --git a/plugins/sdk/deviceModel.go b/plugins/sdk/deviceModel.go
old mode 100644
new mode 100755
diff --git a/react-ui/src/components/devices/reducer/device.reducer.ts b/react-ui/src/components/devices/reducer/device.reducer.ts
index f211fe024..c7538079a 100755
--- a/react-ui/src/components/devices/reducer/device.reducer.ts
+++ b/react-ui/src/components/devices/reducer/device.reducer.ts
@@ -3,7 +3,6 @@ import {
     NetworkelementManagedNetworkElement,
     PndPrincipalNetworkDomain
 } from '@api/api'
-import { DeviceViewTabValues } from '@component/devices/view/device.view.tabs'
 import { createSlice, PayloadAction } from '@reduxjs/toolkit'
 import { refreshUpdateTimer } from '@shared/reducer/routine.reducer'
 import { Category, CategoryType } from '@shared/types/category.type'
@@ -24,14 +23,12 @@ export interface DeviceSliceState {
     devices: Device[]
     pnds: PndPrincipalNetworkDomain[]
 
-    activeTab: DeviceViewTabValues
     selected: SelectedObject | null
 }
 
 const initialState: DeviceSliceState = {
     devices: [],
     pnds: [],
-    activeTab: DeviceViewTabValues.METADATA,
     selected: null,
 }
 
@@ -52,9 +49,6 @@ const deviceSlice = createSlice({
         setPnds: (state, action: PayloadAction<PndPrincipalNetworkDomain[] | undefined>) => {
             state.pnds = action.payload || []
         },
-        setActiveTab: (state, action: PayloadAction<DeviceViewTabValues>) => {
-            state.activeTab = action.payload
-        },
         setSelectedDevice: {
             reducer: (state, { payload, meta }: PayloadAction<SetSelectedDeviceType, string, { skipListener?: boolean }>) => {
                 /**
@@ -110,7 +104,7 @@ const deviceSlice = createSlice({
     },
 })
 
-export const { setDevices, setActiveTab, setSelectedDevice, setSelectedMne, setSelectedJson, setPnds } =
+export const { setDevices, setSelectedDevice, setSelectedMne, setSelectedJson, setPnds } =
     deviceSlice.actions
 
 export default deviceSlice.reducer
diff --git a/react-ui/src/components/devices/view/device.view.table.tsx b/react-ui/src/components/devices/view/device.view.table.tsx
index 1f7221ead..f1eb53130 100755
--- a/react-ui/src/components/devices/view/device.view.table.tsx
+++ b/react-ui/src/components/devices/view/device.view.table.tsx
@@ -1,71 +1,97 @@
+import { faChevronDown } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import { insertMarkTags } from "@helper/text";
 import { useAppSelector } from "@hooks";
 import DOMPurify from 'dompurify';
-import { MutableRefObject, useCallback, useRef } from "react";
-import { OverlayTrigger, Table, Tooltip } from "react-bootstrap";
+import { RefObject, useCallback, useRef, useState } from 'react';
+import { Collapse, OverlayTrigger, Tooltip } from 'react-bootstrap';
 import { useTranslation } from "react-i18next";
+import { Device } from "../reducer/device.reducer";
 import { useDeviceTableViewModel } from "../view_model/device.table.viewmodel";
+import { DeviceListCollapsable } from "./subcomponent/device.view.list-detail";
 
 const cropUUID = (uuid: string): string => {
     return uuid.substring(0, 3) + "..." + uuid.substring(uuid.length - 3, uuid.length);
-}
+};
 
-export const DeviceViewTable = (searchRef: MutableRefObject<HTMLInputElement>) => {
+export const DeviceList = ({ searchRef }: { searchRef: RefObject<HTMLInputElement> }) => {
     const { devices, pnds, selected: selectedDevice } = useAppSelector(state => state.device);
     const { t } = useTranslation('common');
-    const tableRef = useRef();
-    const { trClickHandler } = useDeviceTableViewModel(searchRef, tableRef);
+    const [expandedId, setExpandedId] = useState<string | null | undefined>(null);
+    const listRef = useRef<HTMLDivElement>(null);
+    const { dispatchDevice } = useDeviceTableViewModel(searchRef, listRef);
 
-    const getDeviceTable = useCallback(() => {
-        const search = searchRef.current?.value;
-        let filtered = devices
+    const handleItemClick = useCallback((device: Device) => {
+        dispatchDevice(device)
+
+        const { id } = device
+        setExpandedId(expandedId === id ? null : id);
+    }, [expandedId]);
+
+    const getDeviceList = useCallback(() => {
+        const search = searchRef?.current?.value;
+        let filtered = devices;
 
-        // filter if something is in search
         if (search) {
             filtered = devices.filter((device) => {
                 const user = pnds.find(pnd => pnd.id === device.pid);
-
                 return device.id?.includes(search) ||
                     device.name?.includes(search) ||
                     user?.name?.includes(search);
-            })
+            });
         }
 
-        return filtered.map((device, index) => {
+        return filtered.map((device) => {
             const user = pnds.find(pnd => pnd.id === device.pid);
-
-            const username = user?.name || ''
+            const username = user?.name || '';
             const deviceId = device.id!;
-            const cropedId = cropUUID(deviceId)
+            const croppedId = cropUUID(deviceId);
             const devicename = device.name || '';
-
-            const rowData = username + ";" + deviceId + ";" + devicename
+            const isExpanded = expandedId === deviceId;
+            const isSelected = selectedDevice?.device.id === deviceId;
 
             return (
-                <tr data-copy-value={rowData} key={index} onClick={() => trClickHandler(device)} className={selectedDevice?.device.id === deviceId ? 'active' : ''}>
-                    <td data-copy-value={devicename} dangerouslySetInnerHTML={{ __html: search ? insertMarkTags(devicename, search) : DOMPurify.sanitize(devicename) }}></td>
-                    <OverlayTrigger overlay={<Tooltip id={device.id}>{deviceId}</Tooltip>}>
-                        <td data-copy-value={deviceId} dangerouslySetInnerHTML={{ __html: search ? insertMarkTags(cropedId, search) : DOMPurify.sanitize(cropedId) }}></td>
-                    </OverlayTrigger>
-                    <td data-copy-value={username} dangerouslySetInnerHTML={{ __html: search ? insertMarkTags(username, search) : DOMPurify.sanitize(username) }}></td>
-                </tr>
+                <div
+                    key={deviceId}
+                    className={`border-bottom border-primary p-2 transition-bg ${isSelected && 'bg-gradient-fade'} ${!isSelected && 'text-disabled'}`}
+                >
+                    <div
+                        aria-expanded={isExpanded}
+                        className="d-flex justify-content-between py-4 clickable"
+                        onClick={() => handleItemClick(device)}>
+                        <FontAwesomeIcon icon={faChevronDown} rotation={isExpanded ? undefined : 270} />
+                        <span dangerouslySetInnerHTML={{
+                            __html: search ? insertMarkTags(devicename, search) : DOMPurify.sanitize(devicename)
+                        }} />
+                        <OverlayTrigger overlay={<Tooltip id={deviceId}>{deviceId}</Tooltip>}>
+                            <span className="text-gray-500" dangerouslySetInnerHTML={{
+                                __html: search ? insertMarkTags(croppedId, search) : DOMPurify.sanitize(croppedId)
+                            }} />
+                        </OverlayTrigger>
+                        <span className="text-gray-500" dangerouslySetInnerHTML={{
+                            __html: search ? insertMarkTags(username, search) : DOMPurify.sanitize(username)
+                        }} />
+                    </div>
 
-            )
-        })
-    }, [devices, searchRef, pnds, selectedDevice, trClickHandler]);
+                    <Collapse in={isExpanded}>
+                        <div>
+                            <DeviceListCollapsable deviceId={deviceId} username={username} search={search} />
+                        </div>
+                    </Collapse>
+                </div>
+            );
+        });
+    }, [devices, searchRef, pnds, selectedDevice, expandedId, handleItemClick]);
 
     return (
-        <Table striped responsive className="device-table" ref={tableRef}>
-            <thead>
-                <tr>
-                    <th>{t('device.table.header.name')}</th>
-                    <th>{t('device.table.header.uuid')}</th>
-                    <th>{t('device.table.header.user')}</th>
-                </tr>
-            </thead>
-            <tbody>
-                {getDeviceTable()}
-            </tbody>
-        </Table>
-    )
-}
\ No newline at end of file
+        <div className="rounded border border-primary mt-2">
+            <div className="border-bottom border-primary d-flex justify-content-between px-4 py-2 clickable" onClick={() => handleItemClick(device)}>
+                <FontAwesomeIcon icon={faChevronDown} className="opacity-0" />
+                <span className="font-medium">{t('device.table.header.name')}</span>
+                <span className="font-medium">{t('device.table.header.uuid')}</span>
+                <span className="font-medium">{t('device.table.header.user')}</span>
+            </div>
+            <div ref={listRef}>{getDeviceList()}</div>
+        </div>
+    );
+};
\ No newline at end of file
diff --git a/react-ui/src/components/devices/view/device.view.tabs.tsx b/react-ui/src/components/devices/view/device.view.tabs.tsx
deleted file mode 100755
index ef8ba120f..000000000
--- a/react-ui/src/components/devices/view/device.view.tabs.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-import { useAppSelector } from "@hooks";
-import { JsonViewer } from "../../../shared/components/json_viewer/view/json_viewer.view";
-import { useDeviceTabsViewModel } from "../view_model/device.tabs.viewmodel";
-
-export enum DeviceViewTabValues {
-    METADATA = 'metadata',
-    YANGMODEL = 'yang_model'
-}
-
-export const DeviceViewTabs = (activeTab: DeviceViewTabValues) => {
-    const { selected: selectedDevice } = useAppSelector(state => state.device);
-    const { jsonYang } = useDeviceTabsViewModel();
-
-    const metadataTab = () => {
-        return (
-            <div>
-                {selectedDevice!.mne!.name}
-            </div>
-        )
-    }
-
-    const yangModelTab = () => {
-        return (
-            <>
-                {jsonYang &&
-                    <JsonViewer json={jsonYang} />
-                }
-            </>
-        );
-    }
-
-    const renderLoading = () => {
-        return (
-            <div>
-                Loading...
-            </div>
-        )
-    }
-
-    const renderNoDeviceSelected = () => {
-
-        return (
-            <div>
-                No device selected
-            </div>
-        )
-    }
-
-
-    return (
-        <>
-            {selectedDevice?.mne ? (
-                <>
-                    {activeTab === DeviceViewTabValues.METADATA && metadataTab()}
-                    {activeTab === DeviceViewTabValues.YANGMODEL && yangModelTab()}
-                </>
-            ) :
-                selectedDevice ? renderLoading() : renderNoDeviceSelected()
-            }
-
-        </>
-    );
-}
diff --git a/react-ui/src/components/devices/view/device.view.tsx b/react-ui/src/components/devices/view/device.view.tsx
index 6bd702bf7..3e4b822d0 100755
--- a/react-ui/src/components/devices/view/device.view.tsx
+++ b/react-ui/src/components/devices/view/device.view.tsx
@@ -1,20 +1,20 @@
-import { faGripVertical } from '@fortawesome/free-solid-svg-icons';
+import { faGripVertical, faPlus } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { GridLayout } from '@layout/grid.layout/grid.layout';
 import UpdateIndicator from '@layout/grid.layout/update-inidicator.layout/update-indicator.layout';
+import { JsonViewer } from '@shared/components/json_viewer/view/json_viewer.view';
 import { Category, CategoryType } from '@shared/types/category.type';
 import { useRef } from 'react';
-import { Button, Col, Container, Form, Nav, NavLink, Row } from 'react-bootstrap';
+import { Button, Col, Container, Form, Row } from 'react-bootstrap';
 import { useTranslation } from 'react-i18next';
 import { useDeviceViewModel } from '../view_model/device.viewmodel';
 import './device.scss';
-import { DeviceViewTable } from './device.view.table';
-import { DeviceViewTabValues, DeviceViewTabs } from './device.view.tabs';
+import { DeviceList } from './device.view.table';
 
 const DeviceView = () => {
     const { t } = useTranslation('common');
     const searchRef = useRef<HTMLInputElement>(null);
-    const { activeTab, setActiveTab, handleActiveTabLink } = useDeviceViewModel();
+    const { jsonYang } = useDeviceViewModel();
 
     return (
         <div className='m-4 pt-4'>
@@ -32,20 +32,20 @@ const DeviceView = () => {
                                     <h3 className='text-black-50'>{t('device.title')}</h3>
                                 </Col>
                             </Row>
-                            <Row className='align-items-center'>
+                            <Row>
                                 <Col xs={12} sm={6}>
                                     <Form.Group controlId='device.search' className='p-0 mx-1 pt-2'>
                                         <Form.Control type="text" placeholder={t('device.search.placeholder')} ref={searchRef} />
                                     </Form.Group>
                                 </Col>
-                                <Col xs={12} sm={6} className='pt-2'>
-                                    <Button variant='primary' className='w-100 my-auto'>{t('device.add_device_button')}</Button>
+                                <Col xs={12} sm={{ span: 4, offset: 2 }} className='pt-2'>
+                                    <Button variant='primary' className='float-end'><FontAwesomeIcon icon={faPlus} className='me-1' />{t('device.add_device_button')}</Button>
                                 </Col>
                             </Row>
 
                             <Row className='align-items-start'>
                                 <Col sm={12} className='pt-2'>
-                                    {DeviceViewTable(searchRef)}
+                                    {DeviceList({ searchRef })}
                                 </Col>
                             </Row>
                         </Container>
@@ -60,25 +60,14 @@ const DeviceView = () => {
                             <FontAwesomeIcon icon={faGripVertical} className="drag-handle" />
                             <Row>
                                 <Col xs={12} className='mt-4'>
-                                    <Nav className='justify-content-around'>
-                                        <NavLink
-                                            className={handleActiveTabLink(DeviceViewTabValues.METADATA) + " tab-links"}
-                                            onClick={() => setActiveTab(DeviceViewTabValues.METADATA)}
-                                        >
-                                            {t('device.tabs.metadata.title')}
-                                        </NavLink>
-                                        <NavLink
-                                            className={handleActiveTabLink(DeviceViewTabValues.YANGMODEL) + " tab-links"}
-                                            onClick={() => setActiveTab(DeviceViewTabValues.YANGMODEL)}
-                                        >
-                                            {t('device.tabs.yang_model.title')}
-                                        </NavLink>
-                                    </Nav>
+                                    {t('device.tabs.yang_model.title')}
                                 </Col>
                             </Row>
                             <Row className='align-items-start'>
                                 <Col xs={12}>
-                                    {DeviceViewTabs(activeTab)}
+                                    {jsonYang &&
+                                        <JsonViewer json={jsonYang} />
+                                    }
                                 </Col>
                             </Row>
                         </Container>
diff --git a/react-ui/src/components/devices/view/subcomponent/device.view.list-detail.tsx b/react-ui/src/components/devices/view/subcomponent/device.view.list-detail.tsx
new file mode 100644
index 000000000..6e904313d
--- /dev/null
+++ b/react-ui/src/components/devices/view/subcomponent/device.view.list-detail.tsx
@@ -0,0 +1,72 @@
+import { faChevronDown, faHashtag, faUser } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { insertMarkTags } from "@helper/text";
+import { useAppSelector } from "@hooks";
+import { JsonViewer } from "@shared/components/json_viewer/view/json_viewer.view";
+import DOMPurify from 'dompurify';
+import { useCallback, useEffect, useState } from "react";
+import { Collapse } from "react-bootstrap";
+
+interface DeviceListCollapsableProps {
+    deviceId: string
+    username: string
+    search?: string,
+}
+
+
+export const DeviceListCollapsable = ({ deviceId, username, search }: DeviceListCollapsableProps) => {
+    const { selected } = useAppSelector(state => state.device);
+    const [metadata, setMetadata] = useState<boolean>(false)
+
+
+    useEffect(() => {
+        if (!selected?.json) return;
+    })
+
+
+
+    const content = useCallback(() => {
+        if (!selected?.json) return;
+
+        const key = Object.keys(selected.json).at(2) as keyof typeof selected.json
+        const metadataObject = selected.json[key] as JSON;
+
+        return (
+            <div id={`collapse-${deviceId}`}>
+                <div className="pb-4 pt-1 d-flex flex-column gap-1" >
+                    <div className="d-flex justify-content-between">
+                        <div>
+                            <FontAwesomeIcon className="me-2" icon={faHashtag} />
+                            UUID:
+                        </div>
+                        <span dangerouslySetInnerHTML={{
+                            __html: search ? insertMarkTags(deviceId, search) : DOMPurify.sanitize(deviceId)
+                        }} />
+                    </div>
+                    <div className="d-flex justify-content-between">
+                        <div>
+                            <FontAwesomeIcon className="me-2" icon={faUser} />
+                            User:
+                        </div>
+                        <span>{username}</span>
+                    </div>
+
+                    <div className="d-flex justify-content-between clickable border-top border-dark mt-3 pt-2" aria-expanded={metadata} onClick={() => setMetadata(!metadata)}>
+                        <div>
+                            <FontAwesomeIcon icon={faChevronDown} rotation={metadata ? undefined : 270} />
+                            Metadata:
+                        </div>
+                    </div>
+
+                    <Collapse in={metadata}>
+                        <div id={`collapse-${deviceId}`}>
+                            {JsonViewer({ json: metadataObject, options: { editable: false, searchEnabled: false } })}
+                        </div>
+                    </Collapse>
+                </div>
+            </div >
+        )
+    }, [metadata])
+
+    return content()
+}
\ No newline at end of file
diff --git a/react-ui/src/components/devices/view_model/device.table.viewmodel.ts b/react-ui/src/components/devices/view_model/device.table.viewmodel.ts
index 4b328d639..77ba8ddea 100755
--- a/react-ui/src/components/devices/view_model/device.table.viewmodel.ts
+++ b/react-ui/src/components/devices/view_model/device.table.viewmodel.ts
@@ -7,7 +7,7 @@ import { useEffect, useState } from "react";
 import { useTranslation } from "react-i18next";
 import { toast } from "react-toastify";
 
-export const useDeviceTableViewModel = (searchRef, tableRef) => {
+export const useDeviceTableViewModel = (searchRef, listRef) => {
     const [searchTerm, setSearchTerm] = useState('');
     const dispatch = useAppDispatch();
     const { subscribe } = useMenu();
@@ -16,8 +16,8 @@ export const useDeviceTableViewModel = (searchRef, tableRef) => {
 
 
     const registerMenuOptions = () => {
-        const subscription = subscribe({
-            target: tableRef.current,
+        const subscription = subscribe!({
+            target: listRef.current,
             actions: [
                 {
                     key: t('device.table.actions.copy'),
@@ -61,9 +61,8 @@ export const useDeviceTableViewModel = (searchRef, tableRef) => {
         }
     }
 
-    // seperate use effect to rerun this after tableref and subscribe are initialized
     useEffect(() => {
-        if (!subscribe || !tableRef.current) {
+        if (!subscribe || !listRef?.current) {
             return
         }
 
@@ -72,11 +71,11 @@ export const useDeviceTableViewModel = (searchRef, tableRef) => {
         return () => {
             unsubscribe()
         }
-    }, [tableRef, subscribe])
+    }, [listRef, subscribe])
 
 
     useEffect(() => {
-        if (!searchRef.current) {
+        if (!searchRef?.current) {
             return
         }
 
@@ -93,13 +92,13 @@ export const useDeviceTableViewModel = (searchRef, tableRef) => {
         };
     }, [searchRef]);
 
-    const trClickHandler = (device: Device) => {
+    const dispatchDevice = (device: Device) => {
         dispatch(setSelectedDevice({ device }));
     }
 
 
     return {
         searchTerm,
-        trClickHandler
+        dispatchDevice
     }
 }
\ No newline at end of file
diff --git a/react-ui/src/components/devices/view_model/device.tabs.viewmodel.ts b/react-ui/src/components/devices/view_model/device.tabs.viewmodel.ts
deleted file mode 100755
index af4cc3abb..000000000
--- a/react-ui/src/components/devices/view_model/device.tabs.viewmodel.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import { useAppSelector } from '@hooks'
-import { useMemo } from 'react'
-
-export enum DeviceViewTabValues {
-    METADATA = 'metadata',
-    YANGMODEL = 'yang_model',
-}
-
-export const useDeviceTabsViewModel = () => {
-    const { selected: selectedDevice } = useAppSelector((state) => state.device)
-
-    const getYangModelJSON = (): JSON | null => {
-        if (!selectedDevice?.json) {
-            return null
-        }
-
-        const key = Object.keys(selectedDevice.json).at(1) as keyof typeof selectedDevice.json
-        const innerJson = selectedDevice.json[key]
-
-        if (!(innerJson instanceof Object)) {
-            return null
-        }
-
-        return innerJson
-    }
-
-    const jsonYang = useMemo<JSON | null>(getYangModelJSON, [selectedDevice])
-
-    return {
-        jsonYang,
-    }
-}
diff --git a/react-ui/src/components/devices/view_model/device.viewmodel.ts b/react-ui/src/components/devices/view_model/device.viewmodel.ts
index 1cce2d59a..ba2ee88a9 100755
--- a/react-ui/src/components/devices/view_model/device.viewmodel.ts
+++ b/react-ui/src/components/devices/view_model/device.viewmodel.ts
@@ -1,25 +1,27 @@
-import { setActiveTab as setActiveTabState } from '@component/devices/reducer/device.reducer'
-import { useAppDispatch, useAppSelector } from '@hooks'
-import { DeviceViewTabValues } from '@view/device/device.view.tabs'
-import { useEffect } from 'react'
+import { useAppSelector } from '@hooks'
+import { useMemo } from 'react'
 
 export const useDeviceViewModel = () => {
-    const { activeTab } = useAppSelector((state) => state.device)
-    const dispatch = useAppDispatch()
+    const { selected: selectedDevice } = useAppSelector((state) => state.device)
 
-    useEffect(() => { }, [])
+    const getYangModelJSON = (): JSON | null => {
+        if (!selectedDevice?.json) {
+            return null
+        }
 
-    const handleActiveTabLink = (tabLink: DeviceViewTabValues) => {
-        return activeTab === tabLink ? 'active' : ''
-    }
+        const key = Object.keys(selectedDevice.json).at(1) as keyof typeof selectedDevice.json
+        const innerJson = selectedDevice.json[key]
+
+        if (!(innerJson instanceof Object)) {
+            return null
+        }
 
-    const setActiveTab = (tab: DeviceViewTabValues) => {
-        dispatch(setActiveTabState(tab))
+        return innerJson
     }
 
+    const jsonYang = useMemo<JSON | null>(getYangModelJSON, [selectedDevice])
+
     return {
-        activeTab,
-        setActiveTab,
-        handleActiveTabLink,
+        jsonYang
     }
 }
diff --git a/react-ui/src/index.tsx b/react-ui/src/index.tsx
index 3697efd07..0a8fbbf25 100755
--- a/react-ui/src/index.tsx
+++ b/react-ui/src/index.tsx
@@ -13,7 +13,6 @@ import { PersistGate } from 'redux-persist/integration/react'
 import './i18n/config'
 import './index.scss'
 import { router } from './routes'
-import './shared/icons/icons'
 import { persistor, store } from './stores'
 
 window.env = window.location.hostname === 'localhost' ? 'development' : 'production';
diff --git a/react-ui/src/shared/components/json_viewer/view/json_viewer.scss b/react-ui/src/shared/components/json_viewer/view/json_viewer.scss
index 20befdcbb..8a9a78ae5 100755
--- a/react-ui/src/shared/components/json_viewer/view/json_viewer.scss
+++ b/react-ui/src/shared/components/json_viewer/view/json_viewer.scss
@@ -1,17 +1,11 @@
 @import "/src/shared/style/colors.scss";
 
-.list-group-tr {
-    list-style-type: none;
-    margin: 0;
-    padding: 0 0;
-}
-
 .list-item-td {
     & > td {
         color: lighten(map-get($map: $theme-colors, $key: "black"), 20%) !important;
-        background-color: white !important;
         border: 0;
         padding: 0.2em 0 !important;
+        background-color: transparent !important;
     }
 
     & > td:nth-child(2) {
diff --git a/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx b/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx
index 33e52a397..da107ca93 100755
--- a/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx
+++ b/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx
@@ -9,10 +9,14 @@ import { useJsonViewer } from "../viewmodel/json_viewer.viewmodel"
 import './json_viewer.scss'
 
 type JsonViewerProbs = {
-    json: JSON
+    json: JSON,
+    options?: {
+        searchEnabled?: boolean
+        editable?: boolean
+    }
 }
 
-export const JsonViewer = ({ json }: JsonViewerProbs) => {
+export const JsonViewer = ({ json, options = { searchEnabled: true, editable: true } }: JsonViewerProbs) => {
     const { t } = useTranslation('common');
     const htmlContainer = useRef(null);
     const search = useRef<HTMLInputElement>(null);
@@ -84,14 +88,16 @@ export const JsonViewer = ({ json }: JsonViewerProbs) => {
                     >
                         <td style={{ marginLeft: tabs + 'em' }} className={"d-flex align-items-center "}>{icon}<span>&ensp;<span dangerouslySetInnerHTML={{ __html: concatenatedKey }} /></span></td>
                         <td className="text-element text-truncate" dangerouslySetInnerHTML={{ __html: readableValue }}></td>
-                        <td className="text-end">
-                            <div className="d-flex icons justify-content-end align-items-center">
-                                <FontAwesomeIcon icon={faPenToSquare} size="sm" />
-                                <FontAwesomeIcon icon={faTrashCan} size="sm" />
-                            </div>
-                        </td>
+                        {options?.editable &&
+                            <td className="text-end">
+                                <div className="d-flex icons justify-content-end align-items-center">
+                                    <FontAwesomeIcon icon={faPenToSquare} size="sm" />
+                                    <FontAwesomeIcon icon={faTrashCan} size="sm" />
+                                </div>
+                            </td>
+                        }
                     </tr >
-                    {isObject && collapsed ? renderInner(innerChild, nested + 1, concatenatedKey, path) : ''}
+                    {isObject && collapsed && renderInner(innerChild, nested + 1, concatenatedKey, path)}
                 </React.Fragment >
             )
         })
@@ -99,7 +105,7 @@ export const JsonViewer = ({ json }: JsonViewerProbs) => {
 
     const renderJson = (json: JSON): JSX.Element => {
         return (
-            <Table className="list-group-tr">
+            <Table className="m-0 p-0 list-unstyled">
                 <tbody>
                     {
                         renderInner(json)
@@ -121,19 +127,17 @@ export const JsonViewer = ({ json }: JsonViewerProbs) => {
         )
     }, [json, collapseable, searchTerm])
 
-    const searchHTML = () => {
+    const searchHTML = (): React.ReactElement => {
         return (
-            <>
-                <Form.Group controlId='json_viewer.search' className='p-0 mx-1 pt-2'>
-                    <Form.Control type="text" placeholder={t('device.search.placeholder')} ref={search} />
-                </Form.Group>
-            </>
+            <Form.Group controlId='json_viewer.search' className='p-0 mx-1 pt-2'>
+                <Form.Control type="text" placeholder={t('device.search.placeholder')} ref={search} />
+            </Form.Group>
         )
     }
 
     return (
         <div ref={htmlContainer}>
-            {searchHTML()}
+            {options?.searchEnabled && searchHTML()}
             {breadcrumbHTML}
             {hierarchyHTML}
         </div>
diff --git a/react-ui/src/shared/components/json_viewer/viewmodel/json_viewer.viewmodel.tsx b/react-ui/src/shared/components/json_viewer/viewmodel/json_viewer.viewmodel.tsx
index f0bc92212..832e2b229 100644
--- a/react-ui/src/shared/components/json_viewer/viewmodel/json_viewer.viewmodel.tsx
+++ b/react-ui/src/shared/components/json_viewer/viewmodel/json_viewer.viewmodel.tsx
@@ -67,12 +67,8 @@ export const useJsonViewer = ({ json, search, container }: JsonViewerViewModelTy
     }
 
     const registerMenuOptions = () => {
-        if (!container.current) {
-            return () => { }
-        }
-
-        const subscription = subscribe({
-            target: container.current,
+        const subscription = subscribe!({
+            target: container.current!,
             actions: [
                 {
                     key: t('json_viewer.copy'),
@@ -139,8 +135,18 @@ export const useJsonViewer = ({ json, search, container }: JsonViewerViewModelTy
     }, [searchTerm])
 
     useEffect(() => {
-        const unsubscribe = registerMenuOptions();
+        if (!container.current || !subscribe) {
+            return
+        }
+
+        const unsubscribe = registerMenuOptions()
+
+        return () => {
+            unsubscribe()
+        }
+    }, [subscribe])
 
+    useEffect(() => {
         if (search.current) {
             search.current.addEventListener('input', handleSearchInput)
         }
@@ -149,7 +155,6 @@ export const useJsonViewer = ({ json, search, container }: JsonViewerViewModelTy
             if (search.current) {
                 search.current.removeEventListener('input', handleSearchInput)
             }
-            unsubscribe()
         }
     }, [])
 
diff --git a/react-ui/src/shared/icons/icons.ts b/react-ui/src/shared/icons/icons.ts
deleted file mode 100755
index 9c8791cc9..000000000
--- a/react-ui/src/shared/icons/icons.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import { library } from '@fortawesome/fontawesome-svg-core'
-import { faSpinner } from '@fortawesome/free-solid-svg-icons'
-
-library.add(faSpinner)
\ No newline at end of file
diff --git a/react-ui/src/shared/layouts/grid.layout/grid.layout.tsx b/react-ui/src/shared/layouts/grid.layout/grid.layout.tsx
index c184e655b..710e17889 100644
--- a/react-ui/src/shared/layouts/grid.layout/grid.layout.tsx
+++ b/react-ui/src/shared/layouts/grid.layout/grid.layout.tsx
@@ -15,7 +15,7 @@ export const GridLayout: React.FC<GridLayoutProps> = ({ children }) => {
     const [mounted, setMounted] = useState(false);
     const layouts = {
         lg: [
-            { i: 'device-list', x: 0, y: 0, w: 1, h: 1, minW: 1, minH: 1 },
+            { i: 'device-list', x: 0, y: 0, w: 2, h: 1, minW: 2, minH: 1 },
             { i: 'device-details', x: 2, y: 0, w: 2, h: 1, minW: 2, minH: 1 }
         ]
     };
diff --git a/react-ui/src/shared/style/box.scss b/react-ui/src/shared/style/box.scss
index 53158f515..98475a02e 100755
--- a/react-ui/src/shared/style/box.scss
+++ b/react-ui/src/shared/style/box.scss
@@ -1,17 +1,39 @@
 @import "./colors.scss";
 
-$box-padding: 10px;
+$box-padding: 1em;
 $border-radius: 0.25em;
 $border-width: 2px;
 $transition-duration: 0.3s;
 
 .c-box {
-    padding: $box-padding;
+    padding: $box-padding !important;
     background-color: white;
     position: relative;
-    border-radius: $border-radius;
     transition: box-shadow $transition-duration ease-in-out;
+    @extend .border-gradient;
+    @extend .rounded;
+    box-shadow: $box-shadow;
+
+    &:hover {
+        box-shadow: 0 0.5rem 1rem rgba(map-get($theme-colors, "primary"), 0.2);
+
+        &::before {
+            opacity: 1;
+        }
+    }
+}
+
+.rounded {
+    border-radius: $border-radius;
+}
+
+.abstract-box {
+    padding: $box-padding;
+    font-size: 0.9em;
+    border-radius: calc($border-radius / 2);
+}
 
+.border-gradient {
     background:
         linear-gradient(white, white) padding-box,
         linear-gradient(
@@ -22,7 +44,6 @@ $transition-duration: 0.3s;
             )
             border-box;
     border: $border-width solid transparent;
-    box-shadow: $box-shadow;
 
     &::before {
         content: "";
@@ -42,18 +63,34 @@ $transition-duration: 0.3s;
         opacity: 0;
         transition: opacity $transition-duration ease-in-out;
     }
+}
 
-    &:hover {
-        box-shadow: 0 0.5rem 1rem rgba(map-get($theme-colors, "primary"), 0.2);
+@property --startOpacity {
+    syntax: "<number>";
+    initial-value: 0.35;
+    inherits: false;
+}
 
-        &::before {
-            opacity: 1;
-        }
-    }
+@property --startPosition {
+    syntax: "<percentage>";
+    initial-value: 10%;
+    inherits: false;
 }
 
-.abstract-box {
-    padding: $box-padding;
-    font-size: 0.9em;
-    border-radius: calc($border-radius / 2);
+.bg-gradient-fade {
+    $primary-color: map-get($theme-colors, "primary");
+    background: linear-gradient(
+        to bottom,
+        rgba($primary-color, var(--startOpacity)) var(--startPosition),
+        rgba($primary-color, 0.1) 100%
+    );
+
+    &:hover {
+        --startOpacity: 0.4;
+        --startPosition: 30%;
+    }
+
+    transition:
+        --startOpacity $transition-duration ease-in-out,
+        --startPosition $transition-duration ease-in-out;
 }
diff --git a/react-ui/src/shared/style/colors.scss b/react-ui/src/shared/style/colors.scss
index 4469a4a5b..bbeff3733 100755
--- a/react-ui/src/shared/style/colors.scss
+++ b/react-ui/src/shared/style/colors.scss
@@ -5,7 +5,8 @@ $theme-colors: (
   "danger": #ff0000,
   "warning": #dbd116,
   "dark": #595959,
-  "black": #000000
+  "black": #000000,
+  "disabled": #8e8e8e
 );
 
 $box-shadow: 0px 4px 8px rgba(map-get($theme-colors, "primary"), 0.2);
diff --git a/renovate.json b/renovate.json
old mode 100644
new mode 100755
-- 
GitLab


From 2155d2c35bbe2d7c5387ae39ed30ee1bed3f2ac8 Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@stud.h-da.de>
Date: Mon, 20 Jan 2025 17:18:58 +0100
Subject: [PATCH 54/79] (ui): add metadata information

---
 .../src/components/devices/view/device.scss   | 38 +++++++++
 .../devices/view/device.view.table.tsx        | 12 +--
 .../components/devices/view/device.view.tsx   | 10 +--
 .../subcomponent/device.view.list-detail.tsx  | 80 ++++++++-----------
 .../devices/view_model/device.viewmodel.ts    |  3 +-
 .../src/i18n/locales/en/translations.json     |  3 -
 .../json_viewer/view/json_viewer.view.tsx     | 15 +---
 .../viewmodel/json_viewer.viewmodel.tsx       |  2 +-
 react-ui/src/shared/style/box.scss            | 52 +++++-------
 9 files changed, 108 insertions(+), 107 deletions(-)

diff --git a/react-ui/src/components/devices/view/device.scss b/react-ui/src/components/devices/view/device.scss
index 8d4099fc8..bce275265 100755
--- a/react-ui/src/components/devices/view/device.scss
+++ b/react-ui/src/components/devices/view/device.scss
@@ -55,3 +55,41 @@
         text-decoration: underline;
     }
 }
+.transitions {
+    $transition-duration-hover: 0.1s;
+    $transition-duration-change: 0.2s;
+    transition:
+        --startOpacity $transition-duration-hover ease-in-out,
+        --startPosition $transition-duration-hover ease-in-out;
+}
+
+@property --startOpacity {
+    syntax: "<number>";
+    initial-value: 0.35;
+    inherits: false;
+}
+
+@property --startPosition {
+    syntax: "<percentage>";
+    initial-value: 10%;
+    inherits: false;
+}
+
+.bg-gradient-fade {
+    $primary-color: map-get($theme-colors, "primary");
+    background: linear-gradient(
+        to bottom,
+        rgba($primary-color, var(--startOpacity)) var(--startPosition),
+        rgba($primary-color, 0.1) 100%
+    );
+
+    &:hover {
+        --startOpacity: 0.4;
+        --startPosition: 30%;
+    }
+}
+
+.disabled-hover:hover {
+    $primary-color: rgba(map-get($theme-colors, "dark"), 0.1);
+    background: linear-gradient(to bottom, rgb(223, 223, 223) 1%, white 100%);
+}
diff --git a/react-ui/src/components/devices/view/device.view.table.tsx b/react-ui/src/components/devices/view/device.view.table.tsx
index f1eb53130..ff46862e7 100755
--- a/react-ui/src/components/devices/view/device.view.table.tsx
+++ b/react-ui/src/components/devices/view/device.view.table.tsx
@@ -27,7 +27,7 @@ export const DeviceList = ({ searchRef }: { searchRef: RefObject<HTMLInputElemen
         const { id } = device
         setExpandedId(expandedId === id ? null : id);
     }, [expandedId]);
-
+    1
     const getDeviceList = useCallback(() => {
         const search = searchRef?.current?.value;
         let filtered = devices;
@@ -53,12 +53,14 @@ export const DeviceList = ({ searchRef }: { searchRef: RefObject<HTMLInputElemen
             return (
                 <div
                     key={deviceId}
-                    className={`border-bottom border-primary p-2 transition-bg ${isSelected && 'bg-gradient-fade'} ${!isSelected && 'text-disabled'}`}
+                    className={`border-bottom border-primary p-2 transitions ${isSelected && 'bg-gradient-fade py-2'} ${!isSelected && 'text-disabled disabled-hover'}`}
+                    onClick={() => !isExpanded && handleItemClick(device)}
                 >
                     <div
                         aria-expanded={isExpanded}
-                        className="d-flex justify-content-between py-4 clickable"
-                        onClick={() => handleItemClick(device)}>
+                        className="d-flex justify-content-between py-2 clickable"
+                        onClick={() => isExpanded && handleItemClick(device)}
+                    >
                         <FontAwesomeIcon icon={faChevronDown} rotation={isExpanded ? undefined : 270} />
                         <span dangerouslySetInnerHTML={{
                             __html: search ? insertMarkTags(devicename, search) : DOMPurify.sanitize(devicename)
@@ -85,7 +87,7 @@ export const DeviceList = ({ searchRef }: { searchRef: RefObject<HTMLInputElemen
 
     return (
         <div className="rounded border border-primary mt-2">
-            <div className="border-bottom border-primary d-flex justify-content-between px-4 py-2 clickable" onClick={() => handleItemClick(device)}>
+            <div className="border-bottom border-primary d-flex justify-content-between px-4 py-2 clickable">
                 <FontAwesomeIcon icon={faChevronDown} className="opacity-0" />
                 <span className="font-medium">{t('device.table.header.name')}</span>
                 <span className="font-medium">{t('device.table.header.uuid')}</span>
diff --git a/react-ui/src/components/devices/view/device.view.tsx b/react-ui/src/components/devices/view/device.view.tsx
index 3e4b822d0..350abadd0 100755
--- a/react-ui/src/components/devices/view/device.view.tsx
+++ b/react-ui/src/components/devices/view/device.view.tsx
@@ -14,7 +14,7 @@ import { DeviceList } from './device.view.table';
 const DeviceView = () => {
     const { t } = useTranslation('common');
     const searchRef = useRef<HTMLInputElement>(null);
-    const { jsonYang } = useDeviceViewModel();
+    const { jsonYang, selectedDevice } = useDeviceViewModel();
 
     return (
         <div className='m-4 pt-4'>
@@ -28,8 +28,8 @@ const DeviceView = () => {
                             />
                             <FontAwesomeIcon icon={faGripVertical} className="drag-handle" />
                             <Row>
-                                <Col sm={12} className='mt-4'>
-                                    <h3 className='text-black-50'>{t('device.title')}</h3>
+                                <Col sm={12}>
+                                    <h3 className='c-box-title'>{t('device.title')}</h3>
                                 </Col>
                             </Row>
                             <Row>
@@ -59,8 +59,8 @@ const DeviceView = () => {
                             />
                             <FontAwesomeIcon icon={faGripVertical} className="drag-handle" />
                             <Row>
-                                <Col xs={12} className='mt-4'>
-                                    {t('device.tabs.yang_model.title')}
+                                <Col xs={12}>
+                                    <h3 className='c-box-title'>{t('device.tabs.yang_model.title')} <small>{selectedDevice?.device.name}</small></h3>
                                 </Col>
                             </Row>
                             <Row className='align-items-start'>
diff --git a/react-ui/src/components/devices/view/subcomponent/device.view.list-detail.tsx b/react-ui/src/components/devices/view/subcomponent/device.view.list-detail.tsx
index 6e904313d..7473eba6c 100644
--- a/react-ui/src/components/devices/view/subcomponent/device.view.list-detail.tsx
+++ b/react-ui/src/components/devices/view/subcomponent/device.view.list-detail.tsx
@@ -4,7 +4,7 @@ import { insertMarkTags } from "@helper/text";
 import { useAppSelector } from "@hooks";
 import { JsonViewer } from "@shared/components/json_viewer/view/json_viewer.view";
 import DOMPurify from 'dompurify';
-import { useCallback, useEffect, useState } from "react";
+import { useState } from "react";
 import { Collapse } from "react-bootstrap";
 
 interface DeviceListCollapsableProps {
@@ -13,60 +13,48 @@ interface DeviceListCollapsableProps {
     search?: string,
 }
 
-
 export const DeviceListCollapsable = ({ deviceId, username, search }: DeviceListCollapsableProps) => {
     const { selected } = useAppSelector(state => state.device);
-    const [metadata, setMetadata] = useState<boolean>(false)
-
-
-    useEffect(() => {
-        if (!selected?.json) return;
-    })
-
-
+    const [metadata, setMetadata] = useState<boolean>(true)
 
-    const content = useCallback(() => {
-        if (!selected?.json) return;
+    const json = selected?.json || {}
 
-        const key = Object.keys(selected.json).at(2) as keyof typeof selected.json
-        const metadataObject = selected.json[key] as JSON;
+    const key = Object.keys(json).at(2) as keyof typeof json
+    const metadataObject = json[key] as JSON || {};
 
-        return (
-            <div id={`collapse-${deviceId}`}>
-                <div className="pb-4 pt-1 d-flex flex-column gap-1" >
-                    <div className="d-flex justify-content-between">
-                        <div>
-                            <FontAwesomeIcon className="me-2" icon={faHashtag} />
-                            UUID:
-                        </div>
-                        <span dangerouslySetInnerHTML={{
-                            __html: search ? insertMarkTags(deviceId, search) : DOMPurify.sanitize(deviceId)
-                        }} />
+    return (
+        <div id={`collapse-${deviceId}`}>
+            <div className="pb-4 pt-1 d-flex flex-column gap-1" >
+                <div className="d-flex justify-content-between">
+                    <div>
+                        <FontAwesomeIcon className="me-2" icon={faHashtag} />
+                        UUID:
                     </div>
-                    <div className="d-flex justify-content-between">
-                        <div>
-                            <FontAwesomeIcon className="me-2" icon={faUser} />
-                            User:
-                        </div>
-                        <span>{username}</span>
+                    <span dangerouslySetInnerHTML={{
+                        __html: search ? insertMarkTags(deviceId, search) : DOMPurify.sanitize(deviceId)
+                    }} />
+                </div>
+                <div className="d-flex justify-content-between">
+                    <div>
+                        <FontAwesomeIcon className="me-2" icon={faUser} />
+                        User:
                     </div>
+                    <span>{username}</span>
+                </div>
 
-                    <div className="d-flex justify-content-between clickable border-top border-dark mt-3 pt-2" aria-expanded={metadata} onClick={() => setMetadata(!metadata)}>
-                        <div>
-                            <FontAwesomeIcon icon={faChevronDown} rotation={metadata ? undefined : 270} />
-                            Metadata:
-                        </div>
+                <div className="d-flex justify-content-between clickable border-top border-dark mt-3 pt-1" aria-expanded={metadata} onClick={() => setMetadata(!metadata)}>
+                    <div>
+                        <FontAwesomeIcon icon={faChevronDown} rotation={metadata ? undefined : 270} />
+                        Metadata
                     </div>
-
-                    <Collapse in={metadata}>
-                        <div id={`collapse-${deviceId}`}>
-                            {JsonViewer({ json: metadataObject, options: { editable: false, searchEnabled: false } })}
-                        </div>
-                    </Collapse>
                 </div>
-            </div >
-        )
-    }, [metadata])
 
-    return content()
+                <Collapse in={metadata}>
+                    <div id={`collapse-${deviceId}`}>
+                        {JsonViewer({ json: metadataObject, options: { editable: false, searchEnabled: false } })}
+                    </div>
+                </Collapse>
+            </div>
+        </div >
+    )
 }
\ No newline at end of file
diff --git a/react-ui/src/components/devices/view_model/device.viewmodel.ts b/react-ui/src/components/devices/view_model/device.viewmodel.ts
index ba2ee88a9..f2fd63553 100755
--- a/react-ui/src/components/devices/view_model/device.viewmodel.ts
+++ b/react-ui/src/components/devices/view_model/device.viewmodel.ts
@@ -22,6 +22,7 @@ export const useDeviceViewModel = () => {
     const jsonYang = useMemo<JSON | null>(getYangModelJSON, [selectedDevice])
 
     return {
-        jsonYang
+        jsonYang,
+        selectedDevice
     }
 }
diff --git a/react-ui/src/i18n/locales/en/translations.json b/react-ui/src/i18n/locales/en/translations.json
index 53444b9e0..e23061744 100755
--- a/react-ui/src/i18n/locales/en/translations.json
+++ b/react-ui/src/i18n/locales/en/translations.json
@@ -47,9 +47,6 @@
             },
             "add_device_button": "Add device",
             "tabs": {
-                "metadata": {
-                    "title": "Metadata"
-                },
                 "yang_model": {
                     "title": "YANG Model"
                 }
diff --git a/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx b/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx
index da107ca93..ba53d64d7 100755
--- a/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx
+++ b/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx
@@ -23,18 +23,6 @@ export const JsonViewer = ({ json, options = { searchEnabled: true, editable: tr
 
     const { getSubset, breadcrumbs, isCollapsed, collapseable, collapse, parameterizedJson, searchTerm } = useJsonViewer({ json, search, container: htmlContainer });
 
-    const breadcrumbHTML = useMemo(() => {
-        return (
-            <nav aria-label="breadcrumb">
-                <ol className="breadcrumb">
-                    {breadcrumbs.map(breadcrumb => (
-                        <li key={breadcrumb} className="breadcrumb-item"><a href="#">{breadcrumb}</a></li>
-                    ))}
-                </ol>
-            </nav>
-        )
-    }, [breadcrumbs])
-
     const renderInner = (innerJson: JSON, nested: number = 0, parentKey: string = "", path: string = "/network-instance/0/"): JSX.Element => {
         path += parentKey + (parentKey === "" ? "" : "/")
 
@@ -129,7 +117,7 @@ export const JsonViewer = ({ json, options = { searchEnabled: true, editable: tr
 
     const searchHTML = (): React.ReactElement => {
         return (
-            <Form.Group controlId='json_viewer.search' className='p-0 mx-1 pt-2'>
+            <Form.Group controlId='json_viewer.search' className='p-0 '>
                 <Form.Control type="text" placeholder={t('device.search.placeholder')} ref={search} />
             </Form.Group>
         )
@@ -138,7 +126,6 @@ export const JsonViewer = ({ json, options = { searchEnabled: true, editable: tr
     return (
         <div ref={htmlContainer}>
             {options?.searchEnabled && searchHTML()}
-            {breadcrumbHTML}
             {hierarchyHTML}
         </div>
     )
diff --git a/react-ui/src/shared/components/json_viewer/viewmodel/json_viewer.viewmodel.tsx b/react-ui/src/shared/components/json_viewer/viewmodel/json_viewer.viewmodel.tsx
index 832e2b229..6a0c80c7e 100644
--- a/react-ui/src/shared/components/json_viewer/viewmodel/json_viewer.viewmodel.tsx
+++ b/react-ui/src/shared/components/json_viewer/viewmodel/json_viewer.viewmodel.tsx
@@ -132,7 +132,7 @@ export const useJsonViewer = ({ json, search, container }: JsonViewerViewModelTy
 
         innerSearch(json, searchTerm);
         return parameterizedJsonMap
-    }, [searchTerm])
+    }, [searchTerm, json])
 
     useEffect(() => {
         if (!container.current || !subscribe) {
diff --git a/react-ui/src/shared/style/box.scss b/react-ui/src/shared/style/box.scss
index 98475a02e..62dd6530d 100755
--- a/react-ui/src/shared/style/box.scss
+++ b/react-ui/src/shared/style/box.scss
@@ -1,12 +1,12 @@
 @import "./colors.scss";
 
-$box-padding: 1em;
+$box-padding: 1.5em;
 $border-radius: 0.25em;
 $border-width: 2px;
 $transition-duration: 0.3s;
 
 .c-box {
-    padding: $box-padding !important;
+    padding: $box-padding / 2 $box-padding !important;
     background-color: white;
     position: relative;
     transition: box-shadow $transition-duration ease-in-out;
@@ -23,6 +23,24 @@ $transition-duration: 0.3s;
     }
 }
 
+.c-box-title {
+    $text-color: black;
+    color: $text-color;
+    padding: 0.5em 0;
+    margin-top: 0.2em;
+
+    small {
+        font-size: 0.75em;
+        color: rgba($text-color, 0.65);
+        &::before {
+            content: "(";
+        }
+        &::after {
+            content: ")";
+        }
+    }
+}
+
 .rounded {
     border-radius: $border-radius;
 }
@@ -64,33 +82,3 @@ $transition-duration: 0.3s;
         transition: opacity $transition-duration ease-in-out;
     }
 }
-
-@property --startOpacity {
-    syntax: "<number>";
-    initial-value: 0.35;
-    inherits: false;
-}
-
-@property --startPosition {
-    syntax: "<percentage>";
-    initial-value: 10%;
-    inherits: false;
-}
-
-.bg-gradient-fade {
-    $primary-color: map-get($theme-colors, "primary");
-    background: linear-gradient(
-        to bottom,
-        rgba($primary-color, var(--startOpacity)) var(--startPosition),
-        rgba($primary-color, 0.1) 100%
-    );
-
-    &:hover {
-        --startOpacity: 0.4;
-        --startPosition: 30%;
-    }
-
-    transition:
-        --startOpacity $transition-duration ease-in-out,
-        --startPosition $transition-duration ease-in-out;
-}
-- 
GitLab


From 7cecdc93b01197432686ea1e66d96cd6d279d5a3 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Tue, 21 Jan 2025 07:45:26 +0000
Subject: [PATCH 55/79] [renovate] Update renovate/renovate Docker tag to
 v39.118.2

See merge request danet/gosdn!1173

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 .gitlab/ci/.renovate.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab/ci/.renovate.yml b/.gitlab/ci/.renovate.yml
index 423d5c2b9..45e81fa30 100644
--- a/.gitlab/ci/.renovate.yml
+++ b/.gitlab/ci/.renovate.yml
@@ -1,7 +1,7 @@
 renovate:
     stage: tools
 
-    image: renovate/renovate:39.117.2
+    image: renovate/renovate:39.118.2
 
     variables:
         LOG_LEVEL: debug
-- 
GitLab


From 66adf4b0cfedc05cdafb476e2584d0da7ef11613 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Wed, 22 Jan 2025 07:08:57 +0000
Subject: [PATCH 56/79] [renovate] Update module
 github.com/grpc-ecosystem/grpc-gateway/v2 to v2.26.0

See merge request danet/gosdn!1174

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 4 ++--
 go.sum | 4 ++++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/go.mod b/go.mod
index 37a31d82d..492f06256 100644
--- a/go.mod
+++ b/go.mod
@@ -8,7 +8,7 @@ require (
 	github.com/docker/docker v24.0.9+incompatible
 	github.com/google/go-cmp v0.6.0
 	github.com/google/uuid v1.6.0
-	github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1
+	github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0
 	github.com/mitchellh/go-homedir v1.1.0
 	github.com/openconfig/gnmi v0.12.0
 	github.com/openconfig/goyang v1.6.0
@@ -124,6 +124,6 @@ require (
 	go.uber.org/atomic v1.9.0 // indirect
 	go.uber.org/multierr v1.9.0 // indirect
 	golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
-	google.golang.org/genproto/googleapis/rpc v0.0.0-20250106144421-5f5ef82da422 // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
 	gotest.tools/v3 v3.5.1 // indirect
 )
diff --git a/go.sum b/go.sum
index 59c538b85..b888001cc 100644
--- a/go.sum
+++ b/go.sum
@@ -187,6 +187,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 h1:TmHmbvxPmaegwhDubVz0lICL0J5
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0/go.mod h1:qztMSjm835F2bXf+5HKAPIS5qsmQDqZna/PgVt4rWtI=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0 h1:VD1gqscl4nYs1YxVuSdemTrSgTKrwOWDK0FVFMqm+Cg=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0/go.mod h1:4EgsQoS4TOhJizV+JTFg40qx1Ofh3XmXEQNBpgvNT40=
 github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
 github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
 github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@@ -652,6 +654,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d h1:
 google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20250106144421-5f5ef82da422 h1:3UsHvIr4Wc2aW4brOaSCmcxh9ksica6fHEr8P1XhkYw=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20250106144421-5f5ef82da422/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
-- 
GitLab


From d9a45a21dcc7341310f75132ae44c2da89420092 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Wed, 22 Jan 2025 07:19:37 +0000
Subject: [PATCH 57/79] [renovate] Update renovate/renovate Docker tag to
 v39.120.3

See merge request danet/gosdn!1175

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 .gitlab/ci/.renovate.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab/ci/.renovate.yml b/.gitlab/ci/.renovate.yml
index 45e81fa30..9a945e69d 100644
--- a/.gitlab/ci/.renovate.yml
+++ b/.gitlab/ci/.renovate.yml
@@ -1,7 +1,7 @@
 renovate:
     stage: tools
 
-    image: renovate/renovate:39.118.2
+    image: renovate/renovate:39.120.3
 
     variables:
         LOG_LEVEL: debug
-- 
GitLab


From 17c852ea7c62208831c7ab09f567154aa4ff5592 Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@stud.h-da.de>
Date: Wed, 22 Jan 2025 22:10:33 +0100
Subject: [PATCH 58/79] (ui): add background animation

---
 react-ui/package.json                         |   1 +
 .../devices/view/device.view.list.tsx         |  94 +++++++++++++++
 .../devices/view/device.view.table.tsx        |  99 ----------------
 .../components/devices/view/device.view.tsx   | 112 ++++++++----------
 .../subcomponent/device.view.list-detail.tsx  |  45 +++++--
 ....viewmodel.ts => device.list.viewmodel.ts} |   0
 react-ui/src/index.scss                       |   9 +-
 react-ui/src/index.tsx                        |  30 +++--
 .../components/background/background.view.tsx |  92 ++++++++++++++
 .../shared/components/box/gridBox.view.scss   |  67 +++++++++++
 .../shared/components/box/gridBox.view.tsx    |  37 ++++++
 .../reducer/json_viewer.reducer.ts            |  12 +-
 .../json_viewer/view/json_viewer.view.tsx     |  26 ++--
 .../viewmodel/json_viewer.viewmodel.tsx       |  10 +-
 .../layouts/grid.layout/grid.layout.scss      |   9 +-
 .../layouts/grid.layout/grid.layout.tsx       |  58 +++++++--
 .../protected.layout/protected.layout.tsx     |   8 +-
 react-ui/src/shared/style/box.scss            |  84 -------------
 react-ui/src/shared/style/colors.scss         |  35 ++++++
 react-ui/src/shared/style/index.scss          |  10 +-
 react-ui/src/shared/style/skeleton.scss       |   3 +
 react-ui/yarn.lock                            |   5 +
 22 files changed, 530 insertions(+), 316 deletions(-)
 create mode 100755 react-ui/src/components/devices/view/device.view.list.tsx
 delete mode 100755 react-ui/src/components/devices/view/device.view.table.tsx
 rename react-ui/src/components/devices/view_model/{device.table.viewmodel.ts => device.list.viewmodel.ts} (100%)
 create mode 100644 react-ui/src/shared/components/background/background.view.tsx
 create mode 100644 react-ui/src/shared/components/box/gridBox.view.scss
 create mode 100644 react-ui/src/shared/components/box/gridBox.view.tsx
 delete mode 100755 react-ui/src/shared/style/box.scss
 create mode 100644 react-ui/src/shared/style/skeleton.scss

diff --git a/react-ui/package.json b/react-ui/package.json
index 1f742d78d..8bdbbfa50 100755
--- a/react-ui/package.json
+++ b/react-ui/package.json
@@ -27,6 +27,7 @@
         "react-error-boundary": "^4.1.2",
         "react-grid-layout": "^1.5.0",
         "react-i18next": "^15.0.0",
+        "react-loading-skeleton": "^3.5.0",
         "react-redux": "^9.1.2",
         "react-router-dom": "^6.23.1",
         "react-toastify": "^10.0.5",
diff --git a/react-ui/src/components/devices/view/device.view.list.tsx b/react-ui/src/components/devices/view/device.view.list.tsx
new file mode 100755
index 000000000..53f1580d1
--- /dev/null
+++ b/react-ui/src/components/devices/view/device.view.list.tsx
@@ -0,0 +1,94 @@
+import { insertMarkTags } from "@helper/text";
+import { useAppSelector } from "@hooks";
+import DOMPurify from 'dompurify';
+import { RefObject, useCallback, useRef } from 'react';
+import { Col, OverlayTrigger, Row, Tooltip } from 'react-bootstrap';
+import { useTranslation } from "react-i18next";
+import { Device } from "../reducer/device.reducer";
+import { useDeviceTableViewModel } from "../view_model/device.list.viewmodel";
+
+const cropUUID = (uuid: string): string => {
+    return uuid.substring(0, 3) + "..." + uuid.substring(uuid.length - 3, uuid.length);
+};
+
+export const DeviceList = ({ searchRef }: { searchRef: RefObject<HTMLInputElement> }) => {
+    const { devices, pnds, selected: selectedDevice } = useAppSelector(state => state.device);
+    const { t } = useTranslation('common');
+    const listRef = useRef<HTMLDivElement>(null);
+    const { dispatchDevice } = useDeviceTableViewModel(searchRef, listRef);
+
+    const handleItemClick = useCallback((device: Device) => {
+        dispatchDevice(device)
+    }, []);
+
+    const getDeviceList = useCallback(() => {
+        const search = searchRef?.current?.value;
+        let filtered = devices;
+
+        if (search) {
+            filtered = devices.filter((device) => {
+                const user = pnds.find(pnd => pnd.id === device.pid);
+                return device.id?.includes(search) ||
+                    device.name?.includes(search) ||
+                    user?.name?.includes(search);
+            });
+        }
+
+        return filtered.map((device) => {
+            const user = pnds.find(pnd => pnd.id === device.pid);
+            const username = user?.name || '';
+            const deviceId = device.id!;
+            const croppedId = cropUUID(deviceId);
+            const devicename = device.name || '';
+            const isSelected = selectedDevice?.device.id === deviceId;
+
+            return (
+                <div
+                    key={deviceId}
+                    className={`border-bottom border-primary p-2 transitions ${isSelected && 'bg-gradient-fade py-2'} ${!isSelected && 'text-disabled disabled-hover'}`}
+                    onClick={() => handleItemClick(device)}
+                >
+                    <Row
+                        className="align-items-center clickable"
+                        onClick={() => handleItemClick(device)}
+                    >
+                        <Col xs={12} sm={5} >
+                            <span dangerouslySetInnerHTML={{
+                                __html: search ? insertMarkTags(devicename, search) : DOMPurify.sanitize(devicename)
+                            }} />
+                        </Col>
+                        <Col xs={12} sm={3} >
+                            <OverlayTrigger overlay={<Tooltip id={deviceId}>{deviceId}</Tooltip>}>
+                                <span className="text-gray-500" dangerouslySetInnerHTML={{
+                                    __html: search ? insertMarkTags(croppedId, search) : DOMPurify.sanitize(croppedId)
+                                }} />
+                            </OverlayTrigger>
+                        </Col>
+                        <Col xs={12} sm={4} >
+                            <span className="text-gray-500" dangerouslySetInnerHTML={{
+                                __html: search ? insertMarkTags(username, search) : DOMPurify.sanitize(username)
+                            }} />
+                        </Col>
+                    </Row>
+                </div>
+            );
+        });
+    }, [devices, searchRef, pnds, selectedDevice, handleItemClick]);
+
+    return (
+        <div className="rounded border border-primary mt-2">
+            <Row className="border-bottom border-primary px-2 py-2 mx-0">
+                <Col xs={12} sm={5} >
+                    <span className="font-medium">{t('device.table.header.name')}</span>
+                </Col>
+                <Col xs={12} sm={3} >
+                    <span className="font-medium">{t('device.table.header.uuid')}</span>
+                </Col>
+                <Col xs={12} sm={4} >
+                    <span className="font-medium">{t('device.table.header.user')}</span>
+                </Col>
+            </Row>
+            <div ref={listRef}>{getDeviceList()}</div>
+        </div>
+    );
+};
\ No newline at end of file
diff --git a/react-ui/src/components/devices/view/device.view.table.tsx b/react-ui/src/components/devices/view/device.view.table.tsx
deleted file mode 100755
index ff46862e7..000000000
--- a/react-ui/src/components/devices/view/device.view.table.tsx
+++ /dev/null
@@ -1,99 +0,0 @@
-import { faChevronDown } from "@fortawesome/free-solid-svg-icons";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { insertMarkTags } from "@helper/text";
-import { useAppSelector } from "@hooks";
-import DOMPurify from 'dompurify';
-import { RefObject, useCallback, useRef, useState } from 'react';
-import { Collapse, OverlayTrigger, Tooltip } from 'react-bootstrap';
-import { useTranslation } from "react-i18next";
-import { Device } from "../reducer/device.reducer";
-import { useDeviceTableViewModel } from "../view_model/device.table.viewmodel";
-import { DeviceListCollapsable } from "./subcomponent/device.view.list-detail";
-
-const cropUUID = (uuid: string): string => {
-    return uuid.substring(0, 3) + "..." + uuid.substring(uuid.length - 3, uuid.length);
-};
-
-export const DeviceList = ({ searchRef }: { searchRef: RefObject<HTMLInputElement> }) => {
-    const { devices, pnds, selected: selectedDevice } = useAppSelector(state => state.device);
-    const { t } = useTranslation('common');
-    const [expandedId, setExpandedId] = useState<string | null | undefined>(null);
-    const listRef = useRef<HTMLDivElement>(null);
-    const { dispatchDevice } = useDeviceTableViewModel(searchRef, listRef);
-
-    const handleItemClick = useCallback((device: Device) => {
-        dispatchDevice(device)
-
-        const { id } = device
-        setExpandedId(expandedId === id ? null : id);
-    }, [expandedId]);
-    1
-    const getDeviceList = useCallback(() => {
-        const search = searchRef?.current?.value;
-        let filtered = devices;
-
-        if (search) {
-            filtered = devices.filter((device) => {
-                const user = pnds.find(pnd => pnd.id === device.pid);
-                return device.id?.includes(search) ||
-                    device.name?.includes(search) ||
-                    user?.name?.includes(search);
-            });
-        }
-
-        return filtered.map((device) => {
-            const user = pnds.find(pnd => pnd.id === device.pid);
-            const username = user?.name || '';
-            const deviceId = device.id!;
-            const croppedId = cropUUID(deviceId);
-            const devicename = device.name || '';
-            const isExpanded = expandedId === deviceId;
-            const isSelected = selectedDevice?.device.id === deviceId;
-
-            return (
-                <div
-                    key={deviceId}
-                    className={`border-bottom border-primary p-2 transitions ${isSelected && 'bg-gradient-fade py-2'} ${!isSelected && 'text-disabled disabled-hover'}`}
-                    onClick={() => !isExpanded && handleItemClick(device)}
-                >
-                    <div
-                        aria-expanded={isExpanded}
-                        className="d-flex justify-content-between py-2 clickable"
-                        onClick={() => isExpanded && handleItemClick(device)}
-                    >
-                        <FontAwesomeIcon icon={faChevronDown} rotation={isExpanded ? undefined : 270} />
-                        <span dangerouslySetInnerHTML={{
-                            __html: search ? insertMarkTags(devicename, search) : DOMPurify.sanitize(devicename)
-                        }} />
-                        <OverlayTrigger overlay={<Tooltip id={deviceId}>{deviceId}</Tooltip>}>
-                            <span className="text-gray-500" dangerouslySetInnerHTML={{
-                                __html: search ? insertMarkTags(croppedId, search) : DOMPurify.sanitize(croppedId)
-                            }} />
-                        </OverlayTrigger>
-                        <span className="text-gray-500" dangerouslySetInnerHTML={{
-                            __html: search ? insertMarkTags(username, search) : DOMPurify.sanitize(username)
-                        }} />
-                    </div>
-
-                    <Collapse in={isExpanded}>
-                        <div>
-                            <DeviceListCollapsable deviceId={deviceId} username={username} search={search} />
-                        </div>
-                    </Collapse>
-                </div>
-            );
-        });
-    }, [devices, searchRef, pnds, selectedDevice, expandedId, handleItemClick]);
-
-    return (
-        <div className="rounded border border-primary mt-2">
-            <div className="border-bottom border-primary d-flex justify-content-between px-4 py-2 clickable">
-                <FontAwesomeIcon icon={faChevronDown} className="opacity-0" />
-                <span className="font-medium">{t('device.table.header.name')}</span>
-                <span className="font-medium">{t('device.table.header.uuid')}</span>
-                <span className="font-medium">{t('device.table.header.user')}</span>
-            </div>
-            <div ref={listRef}>{getDeviceList()}</div>
-        </div>
-    );
-};
\ No newline at end of file
diff --git a/react-ui/src/components/devices/view/device.view.tsx b/react-ui/src/components/devices/view/device.view.tsx
index 350abadd0..636991ff1 100755
--- a/react-ui/src/components/devices/view/device.view.tsx
+++ b/react-ui/src/components/devices/view/device.view.tsx
@@ -1,80 +1,68 @@
-import { faGripVertical, faPlus } from '@fortawesome/free-solid-svg-icons';
+import { faPlus } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { GridLayout } from '@layout/grid.layout/grid.layout';
-import UpdateIndicator from '@layout/grid.layout/update-inidicator.layout/update-indicator.layout';
+import { GridBox } from '@shared/components/box/gridBox.view';
 import { JsonViewer } from '@shared/components/json_viewer/view/json_viewer.view';
-import { Category, CategoryType } from '@shared/types/category.type';
 import { useRef } from 'react';
-import { Button, Col, Container, Form, Row } from 'react-bootstrap';
+import { Button, Col, Form, Row } from 'react-bootstrap';
 import { useTranslation } from 'react-i18next';
 import { useDeviceViewModel } from '../view_model/device.viewmodel';
 import './device.scss';
-import { DeviceList } from './device.view.table';
+import { DeviceList } from './device.view.list';
+import { DeviceListCollapsable } from './subcomponent/device.view.list-detail';
 
 const DeviceView = () => {
     const { t } = useTranslation('common');
     const searchRef = useRef<HTMLInputElement>(null);
-    const { jsonYang, selectedDevice } = useDeviceViewModel();
+    const { jsonYang } = useDeviceViewModel();
 
     return (
-        <div className='m-4 pt-4'>
-            <GridLayout>
-                <>
-                    <div key="device-list">
-                        <Container className='c-box hoverable h-100'>
-                            <UpdateIndicator
-                                category={Category.DEVICE as CategoryType}
-                                updateInterval={15000}
-                            />
-                            <FontAwesomeIcon icon={faGripVertical} className="drag-handle" />
-                            <Row>
-                                <Col sm={12}>
-                                    <h3 className='c-box-title'>{t('device.title')}</h3>
-                                </Col>
-                            </Row>
-                            <Row>
-                                <Col xs={12} sm={6}>
-                                    <Form.Group controlId='device.search' className='p-0 mx-1 pt-2'>
-                                        <Form.Control type="text" placeholder={t('device.search.placeholder')} ref={searchRef} />
-                                    </Form.Group>
-                                </Col>
-                                <Col xs={12} sm={{ span: 4, offset: 2 }} className='pt-2'>
-                                    <Button variant='primary' className='float-end'><FontAwesomeIcon icon={faPlus} className='me-1' />{t('device.add_device_button')}</Button>
-                                </Col>
-                            </Row>
+        <GridLayout>
+            <>
+                <div key="device-list">
+                    <GridBox title={t("device.title")}>
+                        <Row className="mb-3 align-items-center">
+                            <Col xs={12} md={6} lg={8}>
+                                <Form.Group controlId='device.search'>
+                                    <Form.Control type="text" placeholder={t('device.search.placeholder')} ref={searchRef} />
+                                </Form.Group>
+                            </Col>
+                            <Col xs={12} md={6} lg={4} className='mt-3 mt-md-0 text-md-end'>
+                                <Button variant='primary'>
+                                    <FontAwesomeIcon icon={faPlus} className='me-2' />
+                                    {t('device.add_device_button')}
+                                </Button>
+                            </Col>
+                        </Row>
+                        <Row>
+                            <Col xs={12} className='h-auto'>
+                                <DeviceList searchRef={searchRef} />
+                            </Col>
+                        </Row>
+                    </GridBox>
+                </div>
 
-                            <Row className='align-items-start'>
-                                <Col sm={12} className='pt-2'>
-                                    {DeviceList({ searchRef })}
-                                </Col>
-                            </Row>
-                        </Container>
-                    </div>
+                <div key="device-metadata">
+                    <GridBox title={t("device.title")}>
+                        <Row>
+                            <Col xs={12} >
+                                <DeviceListCollapsable search={searchRef.current?.value || ''} />
+                            </Col>
+                        </Row>
+                    </GridBox>
+                </div>
 
-                    <div key="device-details">
-                        <Container className='c-box hoverable h-100'>
-                            <UpdateIndicator
-                                category={Category.TAB as CategoryType}
-                                updateInterval={5000}
-                            />
-                            <FontAwesomeIcon icon={faGripVertical} className="drag-handle" />
-                            <Row>
-                                <Col xs={12}>
-                                    <h3 className='c-box-title'>{t('device.tabs.yang_model.title')} <small>{selectedDevice?.device.name}</small></h3>
-                                </Col>
-                            </Row>
-                            <Row className='align-items-start'>
-                                <Col xs={12}>
-                                    {jsonYang &&
-                                        <JsonViewer json={jsonYang} />
-                                    }
-                                </Col>
-                            </Row>
-                        </Container>
-                    </div>
-                </>
-            </GridLayout>
-        </div>
+                <div key="device-details">
+                    <GridBox title={t('device.tabs.yang_model.title')}>
+                        <Row>
+                            <Col xs={12}>
+                                {jsonYang && <JsonViewer json={jsonYang} />}
+                            </Col>
+                        </Row>
+                    </GridBox>
+                </div>
+            </>
+        </GridLayout>
     );
 };
 
diff --git a/react-ui/src/components/devices/view/subcomponent/device.view.list-detail.tsx b/react-ui/src/components/devices/view/subcomponent/device.view.list-detail.tsx
index 7473eba6c..ba146d782 100644
--- a/react-ui/src/components/devices/view/subcomponent/device.view.list-detail.tsx
+++ b/react-ui/src/components/devices/view/subcomponent/device.view.list-detail.tsx
@@ -8,19 +8,33 @@ import { useState } from "react";
 import { Collapse } from "react-bootstrap";
 
 interface DeviceListCollapsableProps {
-    deviceId: string
-    username: string
     search?: string,
 }
 
-export const DeviceListCollapsable = ({ deviceId, username, search }: DeviceListCollapsableProps) => {
+enum Collapsables {
+    Metadata = 1,
+    Config = 2
+}
+
+export const DeviceListCollapsable = ({ search }: DeviceListCollapsableProps) => {
     const { selected } = useAppSelector(state => state.device);
-    const [metadata, setMetadata] = useState<boolean>(true)
+    const [collapseable, setCollapsable] = useState<Collapsables | undefined>(undefined)
 
+    const username = selected?.device.name || "";
+    const deviceId = selected?.device.id || "";
     const json = selected?.json || {}
 
-    const key = Object.keys(json).at(2) as keyof typeof json
-    const metadataObject = json[key] as JSON || {};
+    const metadataKey = Object.keys(json).at(2) as keyof typeof json
+    const metadataObject = json[metadataKey] as JSON || {};
+
+    const configKey = Object.keys(json).at(0) as keyof typeof json
+    const configObject = json[configKey] as JSON || {};
+
+
+    const setCollapsed = (prev: Collapsables) => {
+        const next = collapseable === prev ? undefined : prev;
+        setCollapsable(next);
+    }
 
     return (
         <div id={`collapse-${deviceId}`}>
@@ -42,18 +56,31 @@ export const DeviceListCollapsable = ({ deviceId, username, search }: DeviceList
                     <span>{username}</span>
                 </div>
 
-                <div className="d-flex justify-content-between clickable border-top border-dark mt-3 pt-1" aria-expanded={metadata} onClick={() => setMetadata(!metadata)}>
+                <div className="d-flex justify-content-between clickable border-top border-dark mt-3 pt-3" aria-expanded={collapseable === Collapsables.Metadata} onClick={() => setCollapsed(Collapsables.Metadata)}>
                     <div>
-                        <FontAwesomeIcon icon={faChevronDown} rotation={metadata ? undefined : 270} />
+                        <FontAwesomeIcon icon={faChevronDown} rotation={collapseable === Collapsables.Metadata ? undefined : 270} />
                         Metadata
                     </div>
                 </div>
 
-                <Collapse in={metadata}>
+                <Collapse in={collapseable === Collapsables.Metadata}>
                     <div id={`collapse-${deviceId}`}>
                         {JsonViewer({ json: metadataObject, options: { editable: false, searchEnabled: false } })}
                     </div>
                 </Collapse>
+
+                <div className="d-flex justify-content-between clickable mt-3" aria-expanded={collapseable === Collapsables.Config} onClick={() => setCollapsed(Collapsables.Config)}>
+                    <div>
+                        <FontAwesomeIcon icon={faChevronDown} rotation={collapseable === Collapsables.Config ? undefined : 270} />
+                        Config
+                    </div>
+                </div>
+
+                <Collapse in={collapseable === Collapsables.Config}>
+                    <div id={`collapse-${deviceId}`}>
+                        {JsonViewer({ json: configObject, options: { editable: false, searchEnabled: false } })}
+                    </div>
+                </Collapse>
             </div>
         </div >
     )
diff --git a/react-ui/src/components/devices/view_model/device.table.viewmodel.ts b/react-ui/src/components/devices/view_model/device.list.viewmodel.ts
similarity index 100%
rename from react-ui/src/components/devices/view_model/device.table.viewmodel.ts
rename to react-ui/src/components/devices/view_model/device.list.viewmodel.ts
diff --git a/react-ui/src/index.scss b/react-ui/src/index.scss
index 5c9f184b7..610261473 100755
--- a/react-ui/src/index.scss
+++ b/react-ui/src/index.scss
@@ -1,9 +1,16 @@
 @import "./shared/style/index.scss";
+@import "./shared/style/colors.scss";
 
 body {
     margin: 0;
     -webkit-font-smoothing: antialiased;
     -moz-osx-font-smoothing: grayscale;
 
-    background-color: map-get($theme-colors, bg-primary) !important;
+    // background-color: map-get($theme-colors, bg-primary) !important;
+
+    background: linear-gradient(
+        to top,
+        rgba(lighten(map-get($map: $theme-colors, $key: primary), 20%), 0.1) 0%,
+        rgba(map-get($map: $theme-colors, $key: bg-primary), 0.9) 90%
+    );
 }
diff --git a/react-ui/src/index.tsx b/react-ui/src/index.tsx
index 0a8fbbf25..7d6cfe0ac 100755
--- a/react-ui/src/index.tsx
+++ b/react-ui/src/index.tsx
@@ -1,9 +1,11 @@
 import { UtilsProvider } from '@provider/utils.provider'
+import AnimatedBackground from '@shared/components/background/background.view'
 import i18next from 'i18next'
 import React from 'react'
 import ReactDOM from 'react-dom/client'
 import { ErrorBoundary } from "react-error-boundary"
 import { I18nextProvider } from 'react-i18next'
+import { SkeletonTheme } from 'react-loading-skeleton'
 import { Provider } from 'react-redux'
 import {
     RouterProvider
@@ -19,18 +21,22 @@ window.env = window.location.hostname === 'localhost' ? 'development' : 'product
 
 ReactDOM.createRoot(document.getElementById("root")).render(
     <React.StrictMode>
-        <ErrorBoundary fallback={<div>Something went wrong</div>}>
-            <Provider store={store}>
-                <PersistGate loading={null} persistor={persistor}>
-                    <I18nextProvider i18n={i18next}>
-                        <UtilsProvider>
-                            <ToastContainer />
-                            <RouterProvider router={router} />
-                        </UtilsProvider>
-                    </I18nextProvider>
-                </PersistGate>
-            </Provider>
-        </ErrorBoundary>
+        <AnimatedBackground>
+            <ErrorBoundary fallback={<div>Something went wrong</div>}>
+                <SkeletonTheme height="2em" >
+                    <Provider store={store}>
+                        <PersistGate loading={null} persistor={persistor}>
+                            <I18nextProvider i18n={i18next}>
+                                <UtilsProvider>
+                                    <ToastContainer />
+                                    <RouterProvider router={router} />
+                                </UtilsProvider>
+                            </I18nextProvider>
+                        </PersistGate>
+                    </Provider>
+                </SkeletonTheme>
+            </ErrorBoundary>
+        </AnimatedBackground>
     </React.StrictMode>
 );
 
diff --git a/react-ui/src/shared/components/background/background.view.tsx b/react-ui/src/shared/components/background/background.view.tsx
new file mode 100644
index 000000000..27cf56ceb
--- /dev/null
+++ b/react-ui/src/shared/components/background/background.view.tsx
@@ -0,0 +1,92 @@
+import { useEffect, useRef, useState } from 'react';
+
+const AnimatedBackground = ({ children }) => {
+    const containerRef = useRef(null);
+    const [linePaths, setLinePaths] = useState([]);
+
+    useEffect(() => {
+        const updatePaths = () => {
+            if (containerRef.current) {
+                const box = containerRef.current.getBoundingClientRect();
+                const width = box.width;
+                const height = box.height;
+
+                // Calculate starting points and angles for parallel lines
+                const startX = width * 0;  // Start from right side
+                const startY = height * 0.9; // Start from bottom
+                const endX = width * 1.2;    // End at 30% of width
+                const endY = height * -0.3;   // End at 30% of height
+                const spacing = 80;          // 2em spacing between lines
+
+                // Calculate angle and offsets
+                const angle = Math.atan2(startY - endY, startX - endX);
+                const xOffset = spacing * Math.sin(angle);
+                const yOffset = spacing * Math.cos(angle);
+
+                // Create 5 parallel lines
+                const paths = Array.from({ length: 7 }).map((_, index) => {
+                    const startXOffset = index * xOffset;
+                    const startYOffset = index * yOffset;
+
+                    return `M ${startX - startXOffset} ${startY - startYOffset} 
+                            L ${endX - startXOffset} ${endY - startYOffset}`;
+                });
+
+                setLinePaths(paths);
+            }
+        };
+
+        updatePaths();
+        window.addEventListener('resize', updatePaths);
+        return () => window.removeEventListener('resize', updatePaths);
+    }, []);
+
+    return (
+        <div ref={containerRef} className="position-relative min-vh-100">
+
+            {/* Animated lines */}
+            <div className="position-absolute w-100 h-100">
+                <svg className="w-100 h-100">
+                    {linePaths.map((path, index) => (
+                        <g key={index}>
+                            {/* Background line */}
+                            {/* Animated border */}
+                            <path
+                                d={path}
+                                fill="none"
+                                stroke={`${index % 2 === 0 ? 'rgba(179, 80, 224, 0.4)' : 'rgba(150, 50, 190, .2)'}`}
+                                strokeWidth="2"
+                                strokeLinecap="round"
+                                strokeDasharray="40 240"
+                                style={{
+                                    animation: `dash ${0.4 * index + 20}s linear infinite`,
+                                }}
+                            />
+                        </g>
+                    ))}
+                </svg>
+            </div>
+
+            {/* Content container */}
+            <div className="position-relative" style={{ zIndex: 10 }}>
+                {children}
+            </div>
+
+            <style>
+                {`
+                    @keyframes dash {
+                        from {
+                            stroke-dashoffset: 280;
+                        }
+                        to {
+                            stroke-dashoffset: -280;
+                        }
+                    }
+
+                `}
+            </style>
+        </div>
+    );
+};
+
+export default AnimatedBackground;
\ No newline at end of file
diff --git a/react-ui/src/shared/components/box/gridBox.view.scss b/react-ui/src/shared/components/box/gridBox.view.scss
new file mode 100644
index 000000000..f247f654c
--- /dev/null
+++ b/react-ui/src/shared/components/box/gridBox.view.scss
@@ -0,0 +1,67 @@
+@import "/src/shared/style/colors.scss";
+
+.grid-box:hover .grid-box-dependency {
+    opacity: 0.7;
+    transition: opacity 0.3s ease-in-out;
+}
+
+.grid-box-dependency {
+    opacity: 0.4;
+    font-size: 0.9em;
+}
+
+.grid-box .content {
+    overflow-x: clip;
+    overflow-y: auto;
+}
+
+$box-padding: 1.5em;
+$border-radius: 0.25em;
+$border-width: 2px;
+$transition-duration: 0.3s;
+
+.c-box {
+    padding: $box-padding / 2 $box-padding !important;
+    background-color: white;
+    position: relative;
+    transition: box-shadow $transition-duration ease-in-out;
+    @extend .border-gradient;
+    @extend .rounded;
+    box-shadow: $box-shadow;
+
+    &:hover {
+        box-shadow: 0 0.5rem 1rem rgba(map-get($theme-colors, "primary"), 0.2);
+
+        &::before {
+            opacity: 1;
+        }
+    }
+}
+
+.c-box-title {
+    $text-color: black;
+    color: $text-color;
+    padding: 0.5em 0;
+    margin-top: 0.2em;
+
+    small {
+        font-size: 0.75em;
+        color: rgba($text-color, 0.65);
+        &::before {
+            content: "(";
+        }
+        &::after {
+            content: ")";
+        }
+    }
+}
+
+.rounded {
+    border-radius: $border-radius;
+}
+
+.abstract-box {
+    padding: $box-padding;
+    font-size: 0.9em;
+    border-radius: calc($border-radius / 2);
+}
diff --git a/react-ui/src/shared/components/box/gridBox.view.tsx b/react-ui/src/shared/components/box/gridBox.view.tsx
new file mode 100644
index 000000000..77bed3913
--- /dev/null
+++ b/react-ui/src/shared/components/box/gridBox.view.tsx
@@ -0,0 +1,37 @@
+import { faGripVertical } from "@fortawesome/free-solid-svg-icons"
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
+import UpdateIndicator from "@layout/grid.layout/update-inidicator.layout/update-indicator.layout"
+import { Category, CategoryType } from "@shared/types/category.type"
+import { Col, Container, Row } from "react-bootstrap"
+import './gridBox.view.scss'
+
+interface GridBoxProps {
+    title: string,
+    children: React.ReactNode,
+    className?: string,
+}
+
+
+export const GridBox: React.FC<GridBoxProps> = ({ children, title, className = "" }) => {
+    return (
+        <div className="grid-box h-100">
+            <Container fluid className={`c-box d-flex flex-column h-100 ${className}`}>
+                <div>
+                    <UpdateIndicator
+                        category={Category.DEVICE as CategoryType}
+                        updateInterval={15000}
+                    />
+                    <FontAwesomeIcon icon={faGripVertical} className="drag-handle" />
+                    <Row className="mb-0">
+                        <Col xs={12}>
+                            <h4 className='c-box-title'>{title}</h4>
+                        </Col>
+                    </Row>
+                </div>
+                <div className="flex-grow-1 content">
+                    {children}
+                </div>
+            </Container>
+        </div>
+    )
+}
\ No newline at end of file
diff --git a/react-ui/src/shared/components/json_viewer/reducer/json_viewer.reducer.ts b/react-ui/src/shared/components/json_viewer/reducer/json_viewer.reducer.ts
index dd432535c..093dde850 100755
--- a/react-ui/src/shared/components/json_viewer/reducer/json_viewer.reducer.ts
+++ b/react-ui/src/shared/components/json_viewer/reducer/json_viewer.reducer.ts
@@ -25,8 +25,6 @@ interface CollapsedItem {
 }
 
 export interface ReducerState {
-    breadcrumbs: Array<string>,
-
     /**
      * Meta container containg identifier of
      * all non collapsed json objects
@@ -35,7 +33,6 @@ export interface ReducerState {
 }
 
 const initialState: ReducerState = {
-    breadcrumbs: [],
     collapseContainer: [],
 }
 
@@ -76,14 +73,11 @@ const JsonViewerSlice = createSlice({
                     collapsed: CollapseActions[collapse](item.collapsed)
                 }
             })
-        },
-        setBreadcrumbs: (state, { payload }: PayloadAction<Array<string>>) => {
-            state.breadcrumbs = payload
-        },
-    },
+        }
+    }
 })
 
-export const { toggleCollapse, setBreadcrumbs } = JsonViewerSlice.actions
+export const { toggleCollapse, } = JsonViewerSlice.actions
 
 
 export default JsonViewerSlice.reducer
diff --git a/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx b/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx
index ba53d64d7..68f0d6098 100755
--- a/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx
+++ b/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx
@@ -5,9 +5,11 @@ import DOMPurify from 'dompurify'
 import React, { Suspense, useMemo, useRef } from "react"
 import { Form, Table } from "react-bootstrap"
 import { useTranslation } from "react-i18next"
+import Skeleton from 'react-loading-skeleton'
 import { useJsonViewer } from "../viewmodel/json_viewer.viewmodel"
 import './json_viewer.scss'
 
+
 type JsonViewerProbs = {
     json: JSON,
     options?: {
@@ -21,11 +23,15 @@ export const JsonViewer = ({ json, options = { searchEnabled: true, editable: tr
     const htmlContainer = useRef(null);
     const search = useRef<HTMLInputElement>(null);
 
-    const { getSubset, breadcrumbs, isCollapsed, collapseable, collapse, parameterizedJson, searchTerm } = useJsonViewer({ json, search, container: htmlContainer });
+    const { getSubset, isCollapsed, collapseable, collapse, parameterizedJson, searchTerm } = useJsonViewer({ json, search, container: htmlContainer });
 
     const renderInner = (innerJson: JSON, nested: number = 0, parentKey: string = "", path: string = "/network-instance/0/"): JSX.Element => {
         path += parentKey + (parentKey === "" ? "" : "/")
 
+        if (Object.entries(innerJson).length === 0) {
+            return <Skeleton count={3}></Skeleton>
+        }
+
         return Object.entries(innerJson).map(([key, child]): JSX.Element => {
             let collapsed = isCollapsed(key, nested);
 
@@ -104,18 +110,18 @@ export const JsonViewer = ({ json, options = { searchEnabled: true, editable: tr
     }
 
 
-    const hierarchyHTML = useMemo(() => {
+    const Hierarchy = useMemo(() => {
         const subset = getSubset(json);
         return (
-            <>
-                <Suspense fallback={<div>loading...</div>}>
-                    {renderJson(subset)}
-                </Suspense>
-            </>
+            <Suspense>
+                {renderJson(subset)}
+            </Suspense>
         )
     }, [json, collapseable, searchTerm])
 
-    const searchHTML = (): React.ReactElement => {
+
+
+    const Search = (): React.ReactElement => {
         return (
             <Form.Group controlId='json_viewer.search' className='p-0 '>
                 <Form.Control type="text" placeholder={t('device.search.placeholder')} ref={search} />
@@ -125,8 +131,8 @@ export const JsonViewer = ({ json, options = { searchEnabled: true, editable: tr
 
     return (
         <div ref={htmlContainer}>
-            {options?.searchEnabled && searchHTML()}
-            {hierarchyHTML}
+            {options?.searchEnabled && Search()}
+            {Hierarchy}
         </div>
     )
 }
\ No newline at end of file
diff --git a/react-ui/src/shared/components/json_viewer/viewmodel/json_viewer.viewmodel.tsx b/react-ui/src/shared/components/json_viewer/viewmodel/json_viewer.viewmodel.tsx
index 6a0c80c7e..ccbeac713 100644
--- a/react-ui/src/shared/components/json_viewer/viewmodel/json_viewer.viewmodel.tsx
+++ b/react-ui/src/shared/components/json_viewer/viewmodel/json_viewer.viewmodel.tsx
@@ -19,7 +19,7 @@ interface JsonViewerViewModelType {
 }
 
 export const useJsonViewer = ({ json, search, container }: JsonViewerViewModelType) => {
-    const { breadcrumbs, collapseContainer } = useAppSelector(state => state.json_viwer)
+    const { collapseContainer } = useAppSelector(state => state.json_viwer)
     const dispatch = useAppDispatch();
     const [searchTerm, setSearchTerm] = useState('');
     const { toClipboard } = useUtils();
@@ -31,10 +31,8 @@ export const useJsonViewer = ({ json, search, container }: JsonViewerViewModelTy
     const parameterizedJsonMap = useRef<Array<string>>([]);
 
 
-    const getSubset = (json: JSON) => {
-        const subset = breadcrumbs.reduce((nested, key) => nested?.[key], json);
-
-        let inner = subset;
+    const getSubset = (json: JSON): JSON => {
+        let inner = json;
         const keys: Array<string> = [];
         while (Object.keys(inner).length === 1) {
             const key: string = Object.keys(inner)[0];
@@ -42,7 +40,6 @@ export const useJsonViewer = ({ json, search, container }: JsonViewerViewModelTy
             keys.push(key);
         }
 
-        //dispatch(setBreadcrumbs([...breadcrumbs, ...keys]))
         return inner
     }
 
@@ -160,7 +157,6 @@ export const useJsonViewer = ({ json, search, container }: JsonViewerViewModelTy
 
     return {
         getSubset,
-        breadcrumbs,
         collapseable: collapseContainer,
         isCollapsed,
         collapse,
diff --git a/react-ui/src/shared/layouts/grid.layout/grid.layout.scss b/react-ui/src/shared/layouts/grid.layout/grid.layout.scss
index c90375d37..e1b04be80 100644
--- a/react-ui/src/shared/layouts/grid.layout/grid.layout.scss
+++ b/react-ui/src/shared/layouts/grid.layout/grid.layout.scss
@@ -24,8 +24,6 @@
 }
 
 .react-grid-item {
-    min-height: 600px !important;
-
     &.react-draggable-dragging {
         z-index: 100;
 
@@ -35,12 +33,8 @@
     }
 }
 
-.react-grid-layout {
-    width: 100% !important;
-}
-
 .react-grid-item.react-grid-placeholder {
-    background: lighten(map-get($theme-colors, primary), 30%) !important;
+    background: lighten(map-get($theme-colors, primary), 10%) !important;
     opacity: 0.2;
     transition-duration: 100ms;
     z-index: 2;
@@ -53,6 +47,7 @@
 }
 
 .react-grid-item {
+    height: 100px;
     /* Hide resize handle by default */
     .react-resizable-handle-se {
         opacity: 0;
diff --git a/react-ui/src/shared/layouts/grid.layout/grid.layout.tsx b/react-ui/src/shared/layouts/grid.layout/grid.layout.tsx
index 710e17889..694c74478 100644
--- a/react-ui/src/shared/layouts/grid.layout/grid.layout.tsx
+++ b/react-ui/src/shared/layouts/grid.layout/grid.layout.tsx
@@ -1,4 +1,4 @@
-import React, { ReactElement, useEffect, useState } from 'react';
+import React, { ReactElement, useEffect, useRef, useState } from 'react';
 import { Responsive, WidthProvider } from 'react-grid-layout';
 import 'react-grid-layout/css/styles.css';
 import 'react-resizable/css/styles.css';
@@ -10,20 +10,52 @@ interface GridLayoutProps {
     children: ReactElement;
 }
 
+getComputedStyle
+const RowCount = 2;
+const padding = 80; // in px
+
+
 export const GridLayout: React.FC<GridLayoutProps> = ({ children }) => {
-    const rowHeight = 50;
-    const [mounted, setMounted] = useState(false);
+    const [rowHeight, setRowHeight] = useState<number>(0);
+    const [containerHeight, setContainerHeight] = useState<number>(0);
+    const [mounted, setMounted] = useState<boolean>(false);
+    const containerRef = useRef<HTMLDivElement>(null);
+
     const layouts = {
         lg: [
-            { i: 'device-list', x: 0, y: 0, w: 2, h: 1, minW: 2, minH: 1 },
-            { i: 'device-details', x: 2, y: 0, w: 2, h: 1, minW: 2, minH: 1 }
+            { i: 'device-list', x: 0, y: 0, w: 2, h: 1, minW: 1, minH: 1 },
+            { i: 'device-metadata', x: 0, y: 1, w: 2, h: 1, minW: 1, minH: 1 },
+            { i: 'device-details', x: 2, y: 0, w: 2, h: 2, minW: 1, minH: 1 }
         ]
     };
 
+    const calcHeights = () => {
+        const container = containerRef.current;
+        if (!container) {
+            // Fallback to body height if container is not available
+            const height = document.body.clientHeight * 0.7;
+            setRowHeight(Math.floor(height / RowCount));
+            return;
+        }
+
+        const { top } = container.getBoundingClientRect();
+        const height = document.body.clientHeight - (top + padding);
+        setContainerHeight(height);
+        setRowHeight(Math.floor(height / RowCount));
+        console.log(Math.floor(height / RowCount));
+
+    };
+
+    useEffect(() => {
+        calcHeights();
+    }, [containerRef.current])
+
     useEffect(() => {
         setMounted(true);
-        // Force layout recalculation after mount
-        window.dispatchEvent(new Event('resize'));
+
+
+        window.addEventListener('resize', calcHeights);
+        return () => window.removeEventListener('resize', calcHeights);
     }, []);
 
     const gridItems = React.Children.map(children.props.children, (child, index) => {
@@ -36,12 +68,19 @@ export const GridLayout: React.FC<GridLayoutProps> = ({ children }) => {
     });
 
     return (
-        <div style={{ display: mounted ? 'block' : 'none' }}>
+        <div
+            ref={containerRef}
+            style={{
+                display: mounted ? 'block' : 'none',
+                height: `${containerHeight}px`
+            }}
+        >
             <ResponsiveGridLayout
                 className="layout"
                 layouts={layouts}
                 breakpoints={{ lg: 996, sm: 480 }}
                 cols={{ lg: 4, sm: 3 }}
+                maxRows={RowCount}
                 rowHeight={rowHeight}
                 margin={[20, 20]}
                 draggableHandle=".drag-handle"
@@ -50,7 +89,8 @@ export const GridLayout: React.FC<GridLayoutProps> = ({ children }) => {
                 preventCollision={true}
                 compactType={null}
                 useCSSTransforms={mounted}
-                resizeHandles={['se']} // Only show resize handle in bottom right corner
+                resizeHandles={['se']}
+
             >
                 {gridItems}
             </ResponsiveGridLayout>
diff --git a/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx b/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx
index dbcb49192..4e54f58de 100755
--- a/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx
+++ b/react-ui/src/shared/layouts/protected.layout/protected.layout.tsx
@@ -71,10 +71,10 @@ export const ProtectedLayout = () => {
 
   const HorizontalNavbar = () => {
     return (
-      <Container fluid>
+      <Container fluid className="mb-4">
         <Row>
           <Col>
-            <nav id="navbar" className="bg-white mx-4 mt-4 d-flex align-items-center c-box">
+            <nav id="navbar" className="bg-white mx-4 mt-4 d-flex align-items-center c-box  overflow-visible">
               <Link to="/"><img src={logo} className="mx-4" width={45} alt="logo" /></Link>
               <Link className={"head-links" + handleActiveLink(DEVICE_URL)} to="/">{t('protected.link.device_list')}</Link>
               <Link className={"head-links" + handleActiveLink('/map')} to="/">{t('protected.link.map')}</Link>
@@ -106,7 +106,9 @@ export const ProtectedLayout = () => {
   return (
     <MenuProvider>
       {HorizontalNavbar()}
-      <Outlet />
+      <div className="px-3">
+        <Outlet />
+      </div>
     </MenuProvider>
   )
 };
\ No newline at end of file
diff --git a/react-ui/src/shared/style/box.scss b/react-ui/src/shared/style/box.scss
deleted file mode 100755
index 62dd6530d..000000000
--- a/react-ui/src/shared/style/box.scss
+++ /dev/null
@@ -1,84 +0,0 @@
-@import "./colors.scss";
-
-$box-padding: 1.5em;
-$border-radius: 0.25em;
-$border-width: 2px;
-$transition-duration: 0.3s;
-
-.c-box {
-    padding: $box-padding / 2 $box-padding !important;
-    background-color: white;
-    position: relative;
-    transition: box-shadow $transition-duration ease-in-out;
-    @extend .border-gradient;
-    @extend .rounded;
-    box-shadow: $box-shadow;
-
-    &:hover {
-        box-shadow: 0 0.5rem 1rem rgba(map-get($theme-colors, "primary"), 0.2);
-
-        &::before {
-            opacity: 1;
-        }
-    }
-}
-
-.c-box-title {
-    $text-color: black;
-    color: $text-color;
-    padding: 0.5em 0;
-    margin-top: 0.2em;
-
-    small {
-        font-size: 0.75em;
-        color: rgba($text-color, 0.65);
-        &::before {
-            content: "(";
-        }
-        &::after {
-            content: ")";
-        }
-    }
-}
-
-.rounded {
-    border-radius: $border-radius;
-}
-
-.abstract-box {
-    padding: $box-padding;
-    font-size: 0.9em;
-    border-radius: calc($border-radius / 2);
-}
-
-.border-gradient {
-    background:
-        linear-gradient(white, white) padding-box,
-        linear-gradient(
-                180deg,
-                rgba(map-get($theme-colors, "primary"), 0.4) 0%,
-                rgba(map-get($theme-colors, "primary"), 0.2) 40%,
-                rgba(map-get($theme-colors, "primary"), 0.1) 100%
-            )
-            border-box;
-    border: $border-width solid transparent;
-
-    &::before {
-        content: "";
-        position: absolute;
-        top: -$border-width;
-        left: -$border-width;
-        right: -$border-width;
-        bottom: -$border-width;
-        background: linear-gradient(
-            180deg,
-            rgba(map-get($theme-colors, "primary"), 0.4) 0%,
-            rgba(map-get($theme-colors, "primary"), 0.2) 60%,
-            rgba(map-get($theme-colors, "primary"), 0.1) 100%
-        );
-        border-radius: inherit;
-        z-index: -1;
-        opacity: 0;
-        transition: opacity $transition-duration ease-in-out;
-    }
-}
diff --git a/react-ui/src/shared/style/colors.scss b/react-ui/src/shared/style/colors.scss
index bbeff3733..ce3c3cf90 100755
--- a/react-ui/src/shared/style/colors.scss
+++ b/react-ui/src/shared/style/colors.scss
@@ -10,5 +10,40 @@ $theme-colors: (
 );
 
 $box-shadow: 0px 4px 8px rgba(map-get($theme-colors, "primary"), 0.2);
+$transition-duration: 0.3s;
 
 @import "/node_modules/bootstrap/scss/bootstrap";
+
+// Gradients
+
+.border-gradient {
+  background:
+    linear-gradient(white, white) padding-box,
+    linear-gradient(
+        180deg,
+        rgba(map-get($theme-colors, "primary"), 0.4) 0%,
+        rgba(map-get($theme-colors, "primary"), 0.2) 40%,
+        rgba(map-get($theme-colors, "primary"), 0.1) 100%
+      )
+      border-box;
+  border: $border-width solid transparent;
+
+  &::before {
+    content: "";
+    position: absolute;
+    top: -$border-width;
+    left: -$border-width;
+    right: -$border-width;
+    bottom: -$border-width;
+    background: linear-gradient(
+      180deg,
+      rgba(map-get($theme-colors, "primary"), 0.4) 0%,
+      rgba(map-get($theme-colors, "primary"), 0.2) 60%,
+      rgba(map-get($theme-colors, "primary"), 0.1) 100%
+    );
+    border-radius: inherit;
+    z-index: -1;
+    opacity: 0;
+    transition: opacity $transition-duration ease-in-out;
+  }
+}
diff --git a/react-ui/src/shared/style/index.scss b/react-ui/src/shared/style/index.scss
index e210c8415..b70f6c35e 100755
--- a/react-ui/src/shared/style/index.scss
+++ b/react-ui/src/shared/style/index.scss
@@ -1,5 +1,7 @@
 @import "./fonts.scss";
-@import './colors.scss';
-@import './utils.scss';
-@import './box.scss';
-@import './toast.scss';
+@import "./colors.scss";
+@import "./utils.scss";
+@import "./toast.scss";
+@import "./skeleton.scss";
+
+@import "/node_modules/react-loading-skeleton/dist/skeleton.css";
diff --git a/react-ui/src/shared/style/skeleton.scss b/react-ui/src/shared/style/skeleton.scss
new file mode 100644
index 000000000..680cadd74
--- /dev/null
+++ b/react-ui/src/shared/style/skeleton.scss
@@ -0,0 +1,3 @@
+.react-loading-skeleton {
+    margin: 0.25em 0;
+}
diff --git a/react-ui/yarn.lock b/react-ui/yarn.lock
index db8fb7d3c..224cc0ddd 100755
--- a/react-ui/yarn.lock
+++ b/react-ui/yarn.lock
@@ -8915,6 +8915,11 @@ react-lifecycles-compat@^3.0.4:
   resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
   integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
 
+react-loading-skeleton@^3.5.0:
+  version "3.5.0"
+  resolved "https://registry.yarnpkg.com/react-loading-skeleton/-/react-loading-skeleton-3.5.0.tgz#da2090355b4dedcad5c53cb3f0ed364e3a76d6ca"
+  integrity sha512-gxxSyLbrEAdXTKgfbpBEFZCO/P153DnqSCQau2+o6lNy1jgMRr2MmRmOzMmyrwSaSYLRB8g7b0waYPmUjz7IhQ==
+
 react-redux@^9.1.2:
   version "9.2.0"
   resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-9.2.0.tgz#96c3ab23fb9a3af2cb4654be4b51c989e32366f5"
-- 
GitLab


From 6069e4e17a56458c5d75ec3df3dff31658efdd9a Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@stud.h-da.de>
Date: Thu, 23 Jan 2025 00:24:54 +0100
Subject: [PATCH 59/79] (ui): improve grid layout

---
 .../layouts/grid.layout/grid.layout.scss      | 44 +++++++++++++-
 .../layouts/grid.layout/grid.layout.tsx       | 60 +++++++------------
 2 files changed, 62 insertions(+), 42 deletions(-)

diff --git a/react-ui/src/shared/layouts/grid.layout/grid.layout.scss b/react-ui/src/shared/layouts/grid.layout/grid.layout.scss
index e1b04be80..81ed130dd 100644
--- a/react-ui/src/shared/layouts/grid.layout/grid.layout.scss
+++ b/react-ui/src/shared/layouts/grid.layout/grid.layout.scss
@@ -1,5 +1,47 @@
 @import "/src/shared/style/colors.scss";
 
+.custom-resize-handle {
+    position: absolute;
+    right: 0;
+    bottom: 0;
+    width: 20px;
+    height: 20px;
+    cursor: se-resize;
+
+    .resize-handle-inner {
+        position: absolute;
+        right: 4px;
+        bottom: 4px;
+        width: 12px;
+        height: 12px;
+        border-right: 2px solid rgba(0, 0, 0, 0.2);
+        border-bottom: 2px solid rgba(0, 0, 0, 0.2);
+    }
+}
+
+.react-grid-item {
+    transition: none !important;
+
+    &.resizing {
+        z-index: 1;
+        will-change: transform;
+    }
+}
+
+.react-grid-item {
+    height: 100px;
+    /* Hide resize handle by default */
+    .custom-resize-handle {
+        opacity: 0;
+        transition: opacity 0.2s ease-in-out;
+    }
+
+    /* Show resize handle on container hover */
+    &:hover .custom-resize-handle {
+        opacity: 1;
+    }
+}
+
 .drag-handle {
     position: absolute;
     top: 0;
@@ -25,8 +67,6 @@
 
 .react-grid-item {
     &.react-draggable-dragging {
-        z-index: 100;
-
         .drag-handle {
             cursor: grabbing;
         }
diff --git a/react-ui/src/shared/layouts/grid.layout/grid.layout.tsx b/react-ui/src/shared/layouts/grid.layout/grid.layout.tsx
index 694c74478..7ec2c4a51 100644
--- a/react-ui/src/shared/layouts/grid.layout/grid.layout.tsx
+++ b/react-ui/src/shared/layouts/grid.layout/grid.layout.tsx
@@ -1,19 +1,18 @@
 import React, { ReactElement, useEffect, useRef, useState } from 'react';
-import { Responsive, WidthProvider } from 'react-grid-layout';
+import RGL, { WidthProvider } from "react-grid-layout";
+
 import 'react-grid-layout/css/styles.css';
 import 'react-resizable/css/styles.css';
 import './grid.layout.scss';
 
-const ResponsiveGridLayout = WidthProvider(Responsive);
+const ResponsiveGridLayout = WidthProvider(RGL);
 
 interface GridLayoutProps {
     children: ReactElement;
 }
 
-getComputedStyle
 const RowCount = 2;
-const padding = 80; // in px
-
+const padding = 80;
 
 export const GridLayout: React.FC<GridLayoutProps> = ({ children }) => {
     const [rowHeight, setRowHeight] = useState<number>(0);
@@ -21,81 +20,62 @@ export const GridLayout: React.FC<GridLayoutProps> = ({ children }) => {
     const [mounted, setMounted] = useState<boolean>(false);
     const containerRef = useRef<HTMLDivElement>(null);
 
-    const layouts = {
-        lg: [
-            { i: 'device-list', x: 0, y: 0, w: 2, h: 1, minW: 1, minH: 1 },
-            { i: 'device-metadata', x: 0, y: 1, w: 2, h: 1, minW: 1, minH: 1 },
-            { i: 'device-details', x: 2, y: 0, w: 2, h: 2, minW: 1, minH: 1 }
-        ]
-    };
+    const layouts = [
+        { i: 'device-list', x: 0, y: 0, w: 2, h: 1, minW: 1, minH: 1 },
+        { i: 'device-metadata', x: 0, y: 1, w: 2, h: 1, minW: 1, minH: 1 },
+        { i: 'device-details', x: 3, y: 0, w: 2, h: 2, minW: 1, minH: 1 }
+    ];
 
     const calcHeights = () => {
         const container = containerRef.current;
         if (!container) {
-            // Fallback to body height if container is not available
             const height = document.body.clientHeight * 0.7;
             setRowHeight(Math.floor(height / RowCount));
             return;
         }
-
         const { top } = container.getBoundingClientRect();
         const height = document.body.clientHeight - (top + padding);
         setContainerHeight(height);
         setRowHeight(Math.floor(height / RowCount));
-        console.log(Math.floor(height / RowCount));
-
     };
 
     useEffect(() => {
         calcHeights();
-    }, [containerRef.current])
+    }, [containerRef.current]);
 
     useEffect(() => {
         setMounted(true);
-
-
         window.addEventListener('resize', calcHeights);
         return () => window.removeEventListener('resize', calcHeights);
     }, []);
 
-    const gridItems = React.Children.map(children.props.children, (child, index) => {
-        if (!React.isValidElement(child)) return null;
-
-        return React.cloneElement(child, {
-            key: index === 0 ? 'device-list' : 'device-details',
-            'data-grid': layouts.lg[index]
-        });
-    });
-
     return (
         <div
             ref={containerRef}
             style={{
                 display: mounted ? 'block' : 'none',
-                height: `${containerHeight}px`
+                height: `${containerHeight}px`,
             }}
         >
             <ResponsiveGridLayout
-                className="layout"
-                layouts={layouts}
-                breakpoints={{ lg: 996, sm: 480 }}
-                cols={{ lg: 4, sm: 3 }}
+                cols={5}
+                layout={layouts}
                 maxRows={RowCount}
                 rowHeight={rowHeight}
                 margin={[20, 20]}
                 draggableHandle=".drag-handle"
                 isDraggable={true}
                 isResizable={true}
-                preventCollision={true}
-                compactType={null}
-                useCSSTransforms={mounted}
                 resizeHandles={['se']}
-
+                useCSSTransforms={true}
+                resizeHandle={
+                    <div className="custom-resize-handle">
+                        <div className="resize-handle-inner" />
+                    </div>
+                }
             >
-                {gridItems}
+                {children.props.children}
             </ResponsiveGridLayout>
         </div>
     );
 };
-
-export default GridLayout;
\ No newline at end of file
-- 
GitLab


From d1fbdf41e637b2ceded497cbe8cc75291d7ed8d4 Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@stud.h-da.de>
Date: Thu, 23 Jan 2025 01:00:37 +0100
Subject: [PATCH 60/79] (ui): refactor minor styles

---
 .../src/components/devices/view/device.scss   |  2 +-
 .../components/devices/view/device.view.tsx   | 10 +++----
 .../src/i18n/locales/en/translations.json     | 25 ++++++++++-------
 .../shared/components/box/gridBox.view.tsx    |  8 ++++--
 .../json_viewer/view/json_viewer.scss         |  2 +-
 .../json_viewer/view/json_viewer.view.tsx     |  2 +-
 .../layouts/grid.layout/grid.layout.scss      | 28 -------------------
 .../protected.layout/protected.layout.scss    |  2 +-
 react-ui/src/shared/style/colors.scss         |  3 +-
 9 files changed, 31 insertions(+), 51 deletions(-)

diff --git a/react-ui/src/components/devices/view/device.scss b/react-ui/src/components/devices/view/device.scss
index bce275265..7358cdcf4 100755
--- a/react-ui/src/components/devices/view/device.scss
+++ b/react-ui/src/components/devices/view/device.scss
@@ -6,7 +6,7 @@
     }
 
     & tr:hover > td {
-        background-color: map-get($theme-colors, "primary::hover");
+        background-color: map-get($theme-colors, "primary-hover");
         cursor: pointer;
     }
 
diff --git a/react-ui/src/components/devices/view/device.view.tsx b/react-ui/src/components/devices/view/device.view.tsx
index 636991ff1..290697ac6 100755
--- a/react-ui/src/components/devices/view/device.view.tsx
+++ b/react-ui/src/components/devices/view/device.view.tsx
@@ -1,4 +1,4 @@
-import { faPlus } from '@fortawesome/free-solid-svg-icons';
+import { faCircleInfo, faPlus, faServer, faSliders } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { GridLayout } from '@layout/grid.layout/grid.layout';
 import { GridBox } from '@shared/components/box/gridBox.view';
@@ -20,7 +20,7 @@ const DeviceView = () => {
         <GridLayout>
             <>
                 <div key="device-list">
-                    <GridBox title={t("device.title")}>
+                    <GridBox title={t("device.box.list.title")} title_icon={faServer}>
                         <Row className="mb-3 align-items-center">
                             <Col xs={12} md={6} lg={8}>
                                 <Form.Group controlId='device.search'>
@@ -28,7 +28,7 @@ const DeviceView = () => {
                                 </Form.Group>
                             </Col>
                             <Col xs={12} md={6} lg={4} className='mt-3 mt-md-0 text-md-end'>
-                                <Button variant='primary'>
+                                <Button variant='primary::button' className='btn-primary-button'>
                                     <FontAwesomeIcon icon={faPlus} className='me-2' />
                                     {t('device.add_device_button')}
                                 </Button>
@@ -43,7 +43,7 @@ const DeviceView = () => {
                 </div>
 
                 <div key="device-metadata">
-                    <GridBox title={t("device.title")}>
+                    <GridBox title={t("device.box.information.title")} title_icon={faCircleInfo}>
                         <Row>
                             <Col xs={12} >
                                 <DeviceListCollapsable search={searchRef.current?.value || ''} />
@@ -53,7 +53,7 @@ const DeviceView = () => {
                 </div>
 
                 <div key="device-details">
-                    <GridBox title={t('device.tabs.yang_model.title')}>
+                    <GridBox title={t('device.box.configuration.title')} title_icon={faSliders}>
                         <Row>
                             <Col xs={12}>
                                 {jsonYang && <JsonViewer json={jsonYang} />}
diff --git a/react-ui/src/i18n/locales/en/translations.json b/react-ui/src/i18n/locales/en/translations.json
index e23061744..92fb59d85 100755
--- a/react-ui/src/i18n/locales/en/translations.json
+++ b/react-ui/src/i18n/locales/en/translations.json
@@ -11,6 +11,9 @@
             },
             "menu_item": {
                 "logout": "Logout"
+            },
+            "box": {
+                "lastUpdate": "Last updated {{seconds}} seconds ago"
             }
         },
         "json_viewer": {
@@ -29,7 +32,17 @@
             }
         },
         "device": {
-            "title": "Device list",
+            "box": {
+                "list": {
+                    "title": "Devices"
+                },
+                "information": {
+                    "title": "Information"
+                },
+                "configuration": {
+                    "title": "Configuration"
+                }
+            },
             "table": {
                 "header": {
                     "name": "Name",
@@ -45,15 +58,7 @@
             "search": {
                 "placeholder": "Search"
             },
-            "add_device_button": "Add device",
-            "tabs": {
-                "yang_model": {
-                    "title": "YANG Model"
-                }
-            },
-            "box": {
-                "lastUpdate": "Last updated {{seconds}} seconds ago"
-            }
+            "add_device_button": "Add device"
         },
         "protected": {
             "link": {
diff --git a/react-ui/src/shared/components/box/gridBox.view.tsx b/react-ui/src/shared/components/box/gridBox.view.tsx
index 77bed3913..cc8876100 100644
--- a/react-ui/src/shared/components/box/gridBox.view.tsx
+++ b/react-ui/src/shared/components/box/gridBox.view.tsx
@@ -1,4 +1,4 @@
-import { faGripVertical } from "@fortawesome/free-solid-svg-icons"
+import { faGripVertical, IconDefinition } from "@fortawesome/free-solid-svg-icons"
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
 import UpdateIndicator from "@layout/grid.layout/update-inidicator.layout/update-indicator.layout"
 import { Category, CategoryType } from "@shared/types/category.type"
@@ -7,12 +7,13 @@ import './gridBox.view.scss'
 
 interface GridBoxProps {
     title: string,
+    title_icon: IconDefinition,
     children: React.ReactNode,
     className?: string,
 }
 
 
-export const GridBox: React.FC<GridBoxProps> = ({ children, title, className = "" }) => {
+export const GridBox: React.FC<GridBoxProps> = ({ children, title, title_icon, className = "" }) => {
     return (
         <div className="grid-box h-100">
             <Container fluid className={`c-box d-flex flex-column h-100 ${className}`}>
@@ -24,7 +25,8 @@ export const GridBox: React.FC<GridBoxProps> = ({ children, title, className = "
                     <FontAwesomeIcon icon={faGripVertical} className="drag-handle" />
                     <Row className="mb-0">
                         <Col xs={12}>
-                            <h4 className='c-box-title'>{title}</h4>
+
+                            <h4 className='c-box-title'><FontAwesomeIcon icon={title_icon} size="1x" className="me-2 text-primary" />{title}</h4>
                         </Col>
                     </Row>
                 </div>
diff --git a/react-ui/src/shared/components/json_viewer/view/json_viewer.scss b/react-ui/src/shared/components/json_viewer/view/json_viewer.scss
index 8a9a78ae5..b971de526 100755
--- a/react-ui/src/shared/components/json_viewer/view/json_viewer.scss
+++ b/react-ui/src/shared/components/json_viewer/view/json_viewer.scss
@@ -13,7 +13,7 @@
     }
 
     &:hover > td {
-        background-color: map-get($theme-colors, "primary::hover") !important;
+        background-color: map-get($theme-colors, "primary-hover") !important;
     }
 
     &:hover .icons {
diff --git a/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx b/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx
index 68f0d6098..b2f409c17 100755
--- a/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx
+++ b/react-ui/src/shared/components/json_viewer/view/json_viewer.view.tsx
@@ -29,7 +29,7 @@ export const JsonViewer = ({ json, options = { searchEnabled: true, editable: tr
         path += parentKey + (parentKey === "" ? "" : "/")
 
         if (Object.entries(innerJson).length === 0) {
-            return <Skeleton count={3}></Skeleton>
+            return <tr><td><Skeleton count={3}></Skeleton></td></tr>
         }
 
         return Object.entries(innerJson).map(([key, child]): JSX.Element => {
diff --git a/react-ui/src/shared/layouts/grid.layout/grid.layout.scss b/react-ui/src/shared/layouts/grid.layout/grid.layout.scss
index 81ed130dd..0bacb29b5 100644
--- a/react-ui/src/shared/layouts/grid.layout/grid.layout.scss
+++ b/react-ui/src/shared/layouts/grid.layout/grid.layout.scss
@@ -20,8 +20,6 @@
 }
 
 .react-grid-item {
-    transition: none !important;
-
     &.resizing {
         z-index: 1;
         will-change: transform;
@@ -29,14 +27,11 @@
 }
 
 .react-grid-item {
-    height: 100px;
-    /* Hide resize handle by default */
     .custom-resize-handle {
         opacity: 0;
         transition: opacity 0.2s ease-in-out;
     }
 
-    /* Show resize handle on container hover */
     &:hover .custom-resize-handle {
         opacity: 1;
     }
@@ -65,14 +60,6 @@
     }
 }
 
-.react-grid-item {
-    &.react-draggable-dragging {
-        .drag-handle {
-            cursor: grabbing;
-        }
-    }
-}
-
 .react-grid-item.react-grid-placeholder {
     background: lighten(map-get($theme-colors, primary), 10%) !important;
     opacity: 0.2;
@@ -86,21 +73,6 @@
     user-select: none;
 }
 
-.react-grid-item {
-    height: 100px;
-    /* Hide resize handle by default */
-    .react-resizable-handle-se {
-        opacity: 0;
-        transition: opacity 0.2s ease-in-out;
-    }
-
-    /* Show resize handle on container hover */
-    &:hover .react-resizable-handle-se {
-        opacity: 1;
-    }
-}
-
-/* Style the resize handle */
 .react-resizable-handle-se {
     position: absolute;
     right: 0;
diff --git a/react-ui/src/shared/layouts/protected.layout/protected.layout.scss b/react-ui/src/shared/layouts/protected.layout/protected.layout.scss
index 52429031b..6f255d331 100755
--- a/react-ui/src/shared/layouts/protected.layout/protected.layout.scss
+++ b/react-ui/src/shared/layouts/protected.layout/protected.layout.scss
@@ -39,7 +39,7 @@ nav {
 
         &.active {
             color: map-get($theme-colors, "primary");
-            background-color: map-get($theme-colors, "primary::hover");
+            background-color: map-get($theme-colors, "primary-button");
         }
     }
 
diff --git a/react-ui/src/shared/style/colors.scss b/react-ui/src/shared/style/colors.scss
index ce3c3cf90..9ba6ce0c0 100755
--- a/react-ui/src/shared/style/colors.scss
+++ b/react-ui/src/shared/style/colors.scss
@@ -1,6 +1,7 @@
 $theme-colors: (
   "primary": #b350e0,
-  "primary::hover": #ddaff3af,
+  "primary-hover": #ddaff3af,
+  "primary-button": #ddaff3af,
   "bg-primary": #ededed,
   "danger": #ff0000,
   "warning": #dbd116,
-- 
GitLab


From 54e07d4d9ead78a9ff6940239946193e2724053a Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Thu, 23 Jan 2025 08:52:48 +0000
Subject: [PATCH 61/79] [renovate] Update
 google.golang.org/genproto/googleapis/api digest to 138b5a5

See merge request danet/gosdn!1176

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 2 +-
 go.sum | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/go.mod b/go.mod
index 492f06256..3df1fab0c 100644
--- a/go.mod
+++ b/go.mod
@@ -92,7 +92,7 @@ require (
 	github.com/hashicorp/go-plugin v1.4.10
 	github.com/lesismal/nbio v1.6.0
 	go.mongodb.org/mongo-driver v1.17.2
-	google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f
+	google.golang.org/genproto/googleapis/api v0.0.0-20250122153221-138b5a5a4fd4
 )
 
 require (
diff --git a/go.sum b/go.sum
index b888001cc..ec28bff95 100644
--- a/go.sum
+++ b/go.sum
@@ -628,6 +628,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 h1:
 google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422/go.mod h1:b6h1vNKhxaSoEI+5jc3PJUCustfli/mRab7295pY7rw=
 google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA=
 google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o=
+google.golang.org/genproto/googleapis/api v0.0.0-20250122153221-138b5a5a4fd4 h1://y4MHaM7tNLqTeWKyfBIeoAMxwKwRm/nODb5IKA3BE=
+google.golang.org/genproto/googleapis/api v0.0.0-20250122153221-138b5a5a4fd4/go.mod h1:AfA77qWLcidQWywD0YgqfpJzf50w2VjzBml3TybHeJU=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed h1:J6izYgfBXAI3xTKLgxzTmUltdYaLsuBxFCgDHWJ/eXg=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
-- 
GitLab


From 4528d2d6457ae121065b2d55d2ffbaadd8c5da1c Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Thu, 23 Jan 2025 09:04:11 +0000
Subject: [PATCH 62/79] [renovate] Update renovate/renovate Docker tag to
 v39.124.0

See merge request danet/gosdn!1177

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 .gitlab/ci/.renovate.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab/ci/.renovate.yml b/.gitlab/ci/.renovate.yml
index 9a945e69d..984327afd 100644
--- a/.gitlab/ci/.renovate.yml
+++ b/.gitlab/ci/.renovate.yml
@@ -1,7 +1,7 @@
 renovate:
     stage: tools
 
-    image: renovate/renovate:39.120.3
+    image: renovate/renovate:39.124.0
 
     variables:
         LOG_LEVEL: debug
-- 
GitLab


From 17861377012ecfbccb15a3a6f60361e13856a0d0 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Fri, 24 Jan 2025 08:17:51 +0000
Subject: [PATCH 63/79] [renovate] Update module google.golang.org/grpc to
 v1.70.0

See merge request danet/gosdn!1178

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 4 ++--
 go.sum | 4 ++++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/go.mod b/go.mod
index 3df1fab0c..728d5b0e9 100644
--- a/go.mod
+++ b/go.mod
@@ -24,7 +24,7 @@ require (
 	github.com/stretchr/testify v1.10.0
 	go.mongodb.org/mongo-driver/v2 v2.0.0
 	golang.org/x/sync v0.10.0
-	google.golang.org/grpc v1.69.4
+	google.golang.org/grpc v1.70.0
 	google.golang.org/protobuf v1.36.3
 	gopkg.in/yaml.v3 v3.0.1
 )
@@ -99,7 +99,7 @@ require (
 	atomicgo.dev/cursor v0.2.0 // indirect
 	atomicgo.dev/keyboard v0.2.9 // indirect
 	atomicgo.dev/schedule v0.1.0 // indirect
-	cel.dev/expr v0.18.0 // indirect
+	cel.dev/expr v0.19.0 // indirect
 	github.com/Microsoft/hcsshim v0.12.3 // indirect
 	github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
 	github.com/containerd/console v1.0.3 // indirect
diff --git a/go.sum b/go.sum
index ec28bff95..54dbef9be 100644
--- a/go.sum
+++ b/go.sum
@@ -24,6 +24,8 @@ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.3-2024112718024
 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.3-20241127180247-a33202765966.1/go.mod h1:6VPKM8zbmgf9qsmkmKeH49a36Vtmidw3rG53B5mTenc=
 cel.dev/expr v0.18.0 h1:CJ6drgk+Hf96lkLikr4rFf19WrU0BOWEihyZnI2TAzo=
 cel.dev/expr v0.18.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=
+cel.dev/expr v0.19.0 h1:lXuo+nDhpyJSpWxpPVi5cPUwzKb+dsdOiw6IreM5yt0=
+cel.dev/expr v0.19.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
@@ -680,6 +682,8 @@ google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU=
 google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
 google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A=
 google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
+google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
+google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
-- 
GitLab


From 97483f513c7d9af557c1a83c0ce16a3e7b82e523 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Fri, 24 Jan 2025 09:14:04 +0000
Subject: [PATCH 64/79] [renovate] Update renovate/renovate Docker tag to
 v39.126.1

See merge request danet/gosdn!1179

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 .gitlab/ci/.renovate.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab/ci/.renovate.yml b/.gitlab/ci/.renovate.yml
index 984327afd..78bef9d7e 100644
--- a/.gitlab/ci/.renovate.yml
+++ b/.gitlab/ci/.renovate.yml
@@ -1,7 +1,7 @@
 renovate:
     stage: tools
 
-    image: renovate/renovate:39.124.0
+    image: renovate/renovate:39.126.1
 
     variables:
         LOG_LEVEL: debug
-- 
GitLab


From d0b1d830386aa4a2724e132222539c9501558488 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Tue, 28 Jan 2025 09:32:28 +0000
Subject: [PATCH 65/79] [renovate] Update module google.golang.org/protobuf to
 v1.36.4

See merge request danet/gosdn!1181

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 2 +-
 go.sum | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/go.mod b/go.mod
index 728d5b0e9..5fef5b25a 100644
--- a/go.mod
+++ b/go.mod
@@ -25,7 +25,7 @@ require (
 	go.mongodb.org/mongo-driver/v2 v2.0.0
 	golang.org/x/sync v0.10.0
 	google.golang.org/grpc v1.70.0
-	google.golang.org/protobuf v1.36.3
+	google.golang.org/protobuf v1.36.4
 	gopkg.in/yaml.v3 v3.0.1
 )
 
diff --git a/go.sum b/go.sum
index 54dbef9be..9b856c5b8 100644
--- a/go.sum
+++ b/go.sum
@@ -710,6 +710,8 @@ google.golang.org/protobuf v1.36.2 h1:R8FeyR1/eLmkutZOM5CWghmo5itiG9z0ktFlTVLuTm
 google.golang.org/protobuf v1.36.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=
 google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
+google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
-- 
GitLab


From 4ac41e5bb6707b1afb9baecf70907c935fe833bb Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Tue, 28 Jan 2025 09:44:06 +0000
Subject: [PATCH 66/79] [renovate] Update module
 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go to
 v1.36.4-20241127180247-a33202765966.1

See merge request danet/gosdn!1182

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 2 +-
 go.sum | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/go.mod b/go.mod
index 5fef5b25a..50816a6f0 100644
--- a/go.mod
+++ b/go.mod
@@ -86,7 +86,7 @@ require (
 )
 
 require (
-	buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.3-20241127180247-a33202765966.1
+	buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.4-20241127180247-a33202765966.1
 	github.com/bufbuild/protovalidate-go v0.8.2
 	github.com/hashicorp/go-multierror v1.1.1
 	github.com/hashicorp/go-plugin v1.4.10
diff --git a/go.sum b/go.sum
index 9b856c5b8..f4ed6e757 100644
--- a/go.sum
+++ b/go.sum
@@ -22,6 +22,8 @@ buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.2-2024112718024
 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.2-20241127180247-a33202765966.1/go.mod h1:JnMVLi3qrNYPODVpEKG7UjHLl/d2zR221e66YCSmP2Q=
 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.3-20241127180247-a33202765966.1 h1:cQZXKoQ+eB0kykzfJe80RP3nc+3PWbbBrUBm8XNYAQY=
 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.3-20241127180247-a33202765966.1/go.mod h1:6VPKM8zbmgf9qsmkmKeH49a36Vtmidw3rG53B5mTenc=
+buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.4-20241127180247-a33202765966.1 h1:yeaeyw0RQUe009ebxBQ3TsqBPptiNEGsiS10t+8Htuo=
+buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.4-20241127180247-a33202765966.1/go.mod h1:novQBstnxcGpfKf8qGRATqn1anQKwMJIbH5Q581jibU=
 cel.dev/expr v0.18.0 h1:CJ6drgk+Hf96lkLikr4rFf19WrU0BOWEihyZnI2TAzo=
 cel.dev/expr v0.18.0/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=
 cel.dev/expr v0.19.0 h1:lXuo+nDhpyJSpWxpPVi5cPUwzKb+dsdOiw6IreM5yt0=
-- 
GitLab


From 4d190509d553cbb6e3064aaf0c04d089db025fea Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Tue, 28 Jan 2025 09:52:34 +0000
Subject: [PATCH 67/79] [renovate] Update
 google.golang.org/genproto/googleapis/api digest to 29210b9

See merge request danet/gosdn!1180

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 4 ++--
 go.sum | 4 ++++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/go.mod b/go.mod
index 50816a6f0..342543bd0 100644
--- a/go.mod
+++ b/go.mod
@@ -92,7 +92,7 @@ require (
 	github.com/hashicorp/go-plugin v1.4.10
 	github.com/lesismal/nbio v1.6.0
 	go.mongodb.org/mongo-driver v1.17.2
-	google.golang.org/genproto/googleapis/api v0.0.0-20250122153221-138b5a5a4fd4
+	google.golang.org/genproto/googleapis/api v0.0.0-20250127172529-29210b9bc287
 )
 
 require (
@@ -124,6 +124,6 @@ require (
 	go.uber.org/atomic v1.9.0 // indirect
 	go.uber.org/multierr v1.9.0 // indirect
 	golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
-	google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20250124145028-65684f501c47 // indirect
 	gotest.tools/v3 v3.5.1 // indirect
 )
diff --git a/go.sum b/go.sum
index f4ed6e757..e7ed0a603 100644
--- a/go.sum
+++ b/go.sum
@@ -634,6 +634,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:
 google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o=
 google.golang.org/genproto/googleapis/api v0.0.0-20250122153221-138b5a5a4fd4 h1://y4MHaM7tNLqTeWKyfBIeoAMxwKwRm/nODb5IKA3BE=
 google.golang.org/genproto/googleapis/api v0.0.0-20250122153221-138b5a5a4fd4/go.mod h1:AfA77qWLcidQWywD0YgqfpJzf50w2VjzBml3TybHeJU=
+google.golang.org/genproto/googleapis/api v0.0.0-20250127172529-29210b9bc287 h1:A2ni10G3UlplFrWdCDJTl7D7mJ7GSRm37S+PDimaKRw=
+google.golang.org/genproto/googleapis/api v0.0.0-20250127172529-29210b9bc287/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed h1:J6izYgfBXAI3xTKLgxzTmUltdYaLsuBxFCgDHWJ/eXg=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
@@ -662,6 +664,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250106144421-5f5ef82da422 h1:
 google.golang.org/genproto/googleapis/rpc v0.0.0-20250106144421-5f5ef82da422/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250124145028-65684f501c47 h1:91mG8dNTpkC0uChJUQ9zCiRqx3GEEFOWaRZ0mI6Oj2I=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250124145028-65684f501c47/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
-- 
GitLab


From 11579371b2096e3873e7bb158664528156b1e556 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Tue, 28 Jan 2025 10:02:19 +0000
Subject: [PATCH 68/79] [renovate] Update module github.com/lesismal/nbio to
 v1.6.1

See merge request danet/gosdn!1184

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 2 +-
 go.sum | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/go.mod b/go.mod
index 342543bd0..85321aae1 100644
--- a/go.mod
+++ b/go.mod
@@ -90,7 +90,7 @@ require (
 	github.com/bufbuild/protovalidate-go v0.8.2
 	github.com/hashicorp/go-multierror v1.1.1
 	github.com/hashicorp/go-plugin v1.4.10
-	github.com/lesismal/nbio v1.6.0
+	github.com/lesismal/nbio v1.6.1
 	go.mongodb.org/mongo-driver v1.17.2
 	google.golang.org/genproto/googleapis/api v0.0.0-20250127172529-29210b9bc287
 )
diff --git a/go.sum b/go.sum
index e7ed0a603..3c9264734 100644
--- a/go.sum
+++ b/go.sum
@@ -242,6 +242,8 @@ github.com/lesismal/nbio v1.5.12 h1:YcUjjmOvmKEANs6Oo175JogXvHy8CuE7i6ccjM2/tv4=
 github.com/lesismal/nbio v1.5.12/go.mod h1:QsxE0fKFe1PioyjuHVDn2y8ktYK7xv9MFbpkoRFj8vI=
 github.com/lesismal/nbio v1.6.0 h1:QqkFifnJjcUOzMT8edybXiBa1qlvueYEszy4ZCVroDM=
 github.com/lesismal/nbio v1.6.0/go.mod h1:Ah601gkk8O67QG8uAEz6qP6JHZY4oG0FdWllj3R2Ouc=
+github.com/lesismal/nbio v1.6.1 h1:PUMHD7NpE41KFKmPXS4bmEasAgNTUaD2YR7EGkt8X7s=
+github.com/lesismal/nbio v1.6.1/go.mod h1:Ah601gkk8O67QG8uAEz6qP6JHZY4oG0FdWllj3R2Ouc=
 github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4=
 github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4=
 github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
-- 
GitLab


From 05a58f322302a215bc8fd5029107a2dff3715071 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Wed, 29 Jan 2025 08:13:09 +0000
Subject: [PATCH 69/79] [renovate] Update renovate/renovate Docker tag to
 v39.140.0

See merge request danet/gosdn!1183

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 .gitlab/ci/.renovate.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab/ci/.renovate.yml b/.gitlab/ci/.renovate.yml
index 78bef9d7e..9142bc5b3 100644
--- a/.gitlab/ci/.renovate.yml
+++ b/.gitlab/ci/.renovate.yml
@@ -1,7 +1,7 @@
 renovate:
     stage: tools
 
-    image: renovate/renovate:39.126.1
+    image: renovate/renovate:39.140.0
 
     variables:
         LOG_LEVEL: debug
-- 
GitLab


From 4245ba361fbd556572141ae076820bc3033ebef1 Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@stud.h-da.de>
Date: Wed, 5 Feb 2025 12:59:48 +0100
Subject: [PATCH 70/79] (ui): wip

---
 .../devices/reducer/plugin.reducer.ts         |  99 ++++++++++++
 .../devices/view/subcomponent/modal.view.tsx  | 141 ++++++++++++++++++
 .../devices/view_model/modal.viewmodel.ts     |  10 ++
 3 files changed, 250 insertions(+)
 create mode 100644 react-ui/src/components/devices/reducer/plugin.reducer.ts
 create mode 100644 react-ui/src/components/devices/view/subcomponent/modal.view.tsx
 create mode 100644 react-ui/src/components/devices/view_model/modal.viewmodel.ts

diff --git a/react-ui/src/components/devices/reducer/plugin.reducer.ts b/react-ui/src/components/devices/reducer/plugin.reducer.ts
new file mode 100644
index 000000000..1a09876fe
--- /dev/null
+++ b/react-ui/src/components/devices/reducer/plugin.reducer.ts
@@ -0,0 +1,99 @@
+import {
+    NetworkelementFlattenedManagedNetworkElement,
+    NetworkelementManagedNetworkElement,
+    PndPrincipalNetworkDomain
+} from '@api/api'
+import { createSlice, PayloadAction } from '@reduxjs/toolkit'
+import { refreshUpdateTimer } from '@shared/reducer/routine.reducer'
+import { Category, CategoryType } from '@shared/types/category.type'
+import { REHYDRATE } from 'redux-persist'
+import { RootState } from 'src/stores'
+import '../routines/index'
+import { startListening } from '/src/stores/middleware/listener.middleware'
+
+export type Device = NetworkelementFlattenedManagedNetworkElement
+
+interface SelectedObject {
+    device: Device
+    mne: NetworkelementManagedNetworkElement | null
+    json: JSON | null
+}
+
+export interface DeviceSliceState {
+    devices: Device[]
+    pnds: PndPrincipalNetworkDomain[]
+
+    selected: SelectedObject | null
+}
+
+const initialState: DeviceSliceState = {
+    plugins: [],
+}
+
+interface SetSelectedDeviceType {
+    device: Device | null,
+    options?: {
+        bypassCheck: boolean
+    }
+}
+
+const deviceSlice = createSlice({
+    name: 'plugins',
+    initialState,
+    reducers: {
+        setPlugins: (state, action: PayloadAction<Plugin[] | undefined>) => {
+            state.devices = action.payload || []
+        },
+    },
+})
+
+export const { setDevices, setSelectedDevice, setSelectedMne, setSelectedJson, setPnds } =
+    deviceSlice.actions
+
+export default deviceSlice.reducer
+export const deviceReducerPath = deviceSlice.reducerPath
+
+// add default selected device if no selected device is set
+startListening({
+    predicate: (action) => setDevices.match(action),
+    effect: async (action, listenerApi) => {
+        const { device: state } = listenerApi.getOriginalState() as RootState
+        if (state.selected) {
+            return
+        }
+
+        // if there are no devices available do set null
+        const device = action.payload?.[0] || null
+        listenerApi.dispatch(setSelectedDevice({ device } as SetSelectedDeviceType))
+    },
+})
+
+startListening({
+    predicate: (action) => setSelectedMne.match(action),
+    effect: async (action, listenerApi) => {
+        listenerApi.dispatch(refreshUpdateTimer(Category.TAB as CategoryType))
+    },
+})
+
+startListening({
+    predicate: (action) => setDevices.match(action),
+    effect: async (action, listenerApi) => {
+        listenerApi.dispatch(refreshUpdateTimer(Category.DEVICE as CategoryType))
+    },
+})
+
+/**
+ * On startup reset the selected device 
+ */
+startListening({
+    predicate: ({ type }: any) => type === REHYDRATE,
+    effect: async (_, listenerApi) => {
+        const { device: state } = listenerApi.getState() as RootState
+        const device = state.selected?.device
+        if (!device) {
+            return
+        }
+
+        listenerApi.dispatch(setSelectedDevice({ device, options: { bypassCheck: true } } as SetSelectedDeviceType))
+    },
+})
\ No newline at end of file
diff --git a/react-ui/src/components/devices/view/subcomponent/modal.view.tsx b/react-ui/src/components/devices/view/subcomponent/modal.view.tsx
new file mode 100644
index 000000000..d798e7ade
--- /dev/null
+++ b/react-ui/src/components/devices/view/subcomponent/modal.view.tsx
@@ -0,0 +1,141 @@
+import { NetworkelementAddListRequest, useNetworkElementServiceAddListMutation } from '@api/api';
+import React, { useState } from 'react';
+import { Button, Form, Modal } from 'react-bootstrap';
+
+interface AddDeviceModalProps {
+    show: boolean;
+    onHide: () => void;
+}
+
+interface FormData {
+    address: '',
+    mneName: '',
+    transportOption: undefined,
+    gnmiSubscribePaths: [],
+}
+
+const AddDeviceModal: React.FC<AddDeviceModalProps> = ({ show, onHide }) => {
+    const [addNetworkElement] = useNetworkElementServiceAddListMutation();
+    const [formData, setFormData] = useState<FormData>({
+        address: '',
+        mneName: '',
+        transportOption: undefined,
+        gnmiSubscribePaths: [],
+    });
+
+    const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+        const { name, value } = e.target;
+        setFormData(prev => ({
+            ...prev,
+            [name]: value
+        }));
+    };
+
+    const handleSubmit = async (e: React.FormEvent) => {
+        e.preventDefault();
+
+        const request: NetworkelementAddListRequest = {
+            timestamp: Date.now().toString(), // Convert to nanoseconds if needed
+            mne: [formData],
+            pid: formData.pid
+        };
+
+        try {
+            await addNetworkElement({ networkelementAddListRequest: request });
+            handleReset();
+            // You might want to add a success notification here
+        } catch (error) {
+            console.error('Failed to add device:', error);
+            // You might want to add an error notification here
+        }
+    };
+
+    const handleReset = () => {
+        setFormData({
+            address: '',
+            pid: '',
+            pluginId: '',
+            mneName: '',
+            transportOption: undefined,
+            gnmiSubscribePaths: [],
+            mneId: ''
+        });
+        onHide();
+    };
+
+    return (
+        <Modal show={show} onHide={handleReset} centered>
+            <Modal.Header closeButton>
+                <Modal.Title>Add New Device</Modal.Title>
+            </Modal.Header>
+            <Form onSubmit={handleSubmit}>
+                <Modal.Body>
+                    <Form.Group className="mb-3">
+                        <Form.Label>Address</Form.Label>
+                        <Form.Control
+                            type="text"
+                            name="address"
+                            value={formData.address}
+                            onChange={handleInputChange}
+                            placeholder="Enter device address"
+                        />
+                    </Form.Group>
+
+                    <Form.Group className="mb-3">
+                        <Form.Label>PID</Form.Label>
+                        <Form.Control
+                            type="text"
+                            name="pid"
+                            value={formData.pid}
+                            onChange={handleInputChange}
+                            placeholder="Enter PID"
+                        />
+                    </Form.Group>
+
+                    <Form.Group className="mb-3">
+                        <Form.Label>Plugin ID</Form.Label>
+                        <Form.Control
+                            type="text"
+                            name="pluginId"
+                            value={formData.pluginId}
+                            onChange={handleInputChange}
+                            placeholder="Enter plugin ID"
+                        />
+                    </Form.Group>
+
+                    <Form.Group className="mb-3">
+                        <Form.Label>MNE Name</Form.Label>
+                        <Form.Control
+                            type="text"
+                            name="mneName"
+                            value={formData.mneName}
+                            onChange={handleInputChange}
+                            placeholder="Enter MNE name"
+                        />
+                    </Form.Group>
+
+                    <Form.Group className="mb-3">
+                        <Form.Label>MNE ID</Form.Label>
+                        <Form.Control
+                            type="text"
+                            name="mneId"
+                            value={formData.mneId}
+                            onChange={handleInputChange}
+                            placeholder="Enter MNE ID"
+                        />
+                    </Form.Group>
+                </Modal.Body>
+                <Modal.Footer>
+                    <Button variant="secondary" onClick={handleReset}>
+                        Cancel
+                    </Button>
+                    <Button variant="primary" type="submit">
+                        Add Device
+                    </Button>
+                </Modal.Footer>
+            </Form>
+        </Modal>
+    );
+};
+
+export default AddDeviceModal;
\ No newline at end of file
diff --git a/react-ui/src/components/devices/view_model/modal.viewmodel.ts b/react-ui/src/components/devices/view_model/modal.viewmodel.ts
new file mode 100644
index 000000000..de9bbf68e
--- /dev/null
+++ b/react-ui/src/components/devices/view_model/modal.viewmodel.ts
@@ -0,0 +1,10 @@
+import { useEffect } from "react"
+
+
+export const useModalViewModel = () => {
+
+
+    useEffect(() => {
+
+    }, [])
+}
\ No newline at end of file
-- 
GitLab


From 72ddbd4a5e116a1e26eccbbe0d0ac653d5ff8dae Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@stud.h-da.de>
Date: Wed, 5 Feb 2025 13:00:25 +0100
Subject: [PATCH 71/79] (ui): added pluing fetch endpoint

---
 .../gnmi/proto/collector/collector.pb.go      |  25 +-
 .../openconfig/gnmi/proto/gnmi/gnmi.pb.go     | 426 ++++++------
 .../gnmi/proto/gnmi_ext/gnmi_ext.pb.go        | 121 ++--
 .../openconfig/gnmi/proto/target/target.pb.go |  49 +-
 .../gnmi/testing/fake/proto/fake.pb.go        | 397 ++++++-----
 api/go/gosdn/app/app.pb.go                    |  52 +-
 api/go/gosdn/app/app.pb.gw.go                 | 104 ++-
 .../configurationmanagement.pb.go             |  50 +-
 .../configurationmanagement.pb.gw.go          | 130 +---
 api/go/gosdn/conflict/conflict.pb.go          |  23 +-
 api/go/gosdn/csbi/csbi.pb.go                  | 113 ++-
 .../gosdn/networkelement/networkelement.pb.go | 421 ++++++------
 .../networkelement/networkelement.pb.gw.go    | 648 +++++-------------
 .../plugin-internal/plugin-internal.pb.go     | 233 ++++---
 .../plugin-internal/plugin-internal.pb.gw.go  | 162 +++++
 .../plugin-internal_grpc.pb.go                |  42 +-
 .../plugin-registry/plugin-registry.pb.go     | 379 ++++++----
 .../plugin-registry/plugin-registry.pb.gw.go  | 162 +++++
 api/go/gosdn/plugin/plugin.pb.go              | 558 ++++++++-------
 api/go/gosdn/plugin/plugin.pb.gw.go           | 162 +++++
 api/go/gosdn/plugin/plugin_grpc.pb.go         |  57 +-
 api/go/gosdn/pnd/pnd.pb.go                    | 100 ++-
 api/go/gosdn/pnd/pnd.pb.gw.go                 | 226 ++----
 api/go/gosdn/rbac/rbac.pb.go                  |  50 +-
 api/go/gosdn/rbac/rbac.pb.gw.go               | 120 ++--
 api/go/gosdn/rbac/role.pb.go                  | 131 ++--
 api/go/gosdn/rbac/role.pb.gw.go               | 288 +++-----
 api/go/gosdn/rbac/user.pb.go                  | 132 ++--
 api/go/gosdn/rbac/user.pb.gw.go               | 234 +++----
 api/go/gosdn/southbound/southbound.pb.go      |  41 +-
 .../subscriptionmanagement.pb.go              | 135 ++--
 .../subscriptionmanagement.pb.gw.go           | 296 +++-----
 api/go/gosdn/topology/link.pb.go              |  33 +-
 api/go/gosdn/topology/node.pb.go              |  25 +-
 api/go/gosdn/topology/port.pb.go              |  36 +-
 api/go/gosdn/topology/route.pb.go             |  42 +-
 api/go/gosdn/topology/routingTable.pb.go      |  62 +-
 api/go/gosdn/topology/routingTable.pb.gw.go   | 150 ++--
 api/go/gosdn/topology/topology.pb.go          |  85 +--
 api/go/gosdn/topology/topology.pb.gw.go       | 196 ++----
 api/go/gosdn/transport/transport.pb.go        |  68 +-
 api/openapiv2/gosdn_northbound.swagger.json   |  31 +
 .../gosdn/networkelement/networkelement.proto |   2 +-
 .../plugin-internal/plugin-internal.proto     |  15 +-
 .../plugin-registry/plugin-registry.proto     |  11 +
 api/proto/gosdn/plugin/plugin.proto           |   8 +
 controller/controller.go                      |   1 +
 controller/http.go                            |   6 +
 controller/northbound/server/plugin.go        |  16 +
 .../src/components/login/view/login.view.tsx  |   2 +-
 50 files changed, 3348 insertions(+), 3508 deletions(-)
 create mode 100644 api/go/gosdn/plugin-internal/plugin-internal.pb.gw.go
 create mode 100644 api/go/gosdn/plugin-registry/plugin-registry.pb.gw.go
 create mode 100644 api/go/gosdn/plugin/plugin.pb.gw.go

diff --git a/api/go/github.com/openconfig/gnmi/proto/collector/collector.pb.go b/api/go/github.com/openconfig/gnmi/proto/collector/collector.pb.go
index 09e16b605..3eba4d236 100755
--- a/api/go/github.com/openconfig/gnmi/proto/collector/collector.pb.go
+++ b/api/go/github.com/openconfig/gnmi/proto/collector/collector.pb.go
@@ -16,7 +16,7 @@
 
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: github.com/openconfig/gnmi/proto/collector/collector.proto
 
@@ -27,6 +27,7 @@ import (
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -37,11 +38,10 @@ const (
 )
 
 type ReconnectRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Target        []string               `protobuf:"bytes,1,rep,name=target,proto3" json:"target,omitempty"` // List of targets to reconnect.
 	unknownFields protoimpl.UnknownFields
-
-	Target []string `protobuf:"bytes,1,rep,name=target,proto3" json:"target,omitempty"` // List of targets to reconnect.
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *ReconnectRequest) Reset() {
@@ -82,9 +82,9 @@ func (x *ReconnectRequest) GetTarget() []string {
 }
 
 type Nil struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
 	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Nil) Reset() {
@@ -119,7 +119,7 @@ func (*Nil) Descriptor() ([]byte, []int) {
 
 var File_github_com_openconfig_gnmi_proto_collector_collector_proto protoreflect.FileDescriptor
 
-var file_github_com_openconfig_gnmi_proto_collector_collector_proto_rawDesc = []byte{
+var file_github_com_openconfig_gnmi_proto_collector_collector_proto_rawDesc = string([]byte{
 	0x0a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65,
 	0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x67, 0x6e, 0x6d, 0x69, 0x2f, 0x70, 0x72, 0x6f,
 	0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x2f, 0x63, 0x6f, 0x6c,
@@ -135,16 +135,16 @@ var file_github_com_openconfig_gnmi_proto_collector_collector_proto_rawDesc = []
 	0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x67, 0x6e,
 	0x6d, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74,
 	0x6f, 0x72, 0x3b, 0x67, 0x6e, 0x6d, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_github_com_openconfig_gnmi_proto_collector_collector_proto_rawDescOnce sync.Once
-	file_github_com_openconfig_gnmi_proto_collector_collector_proto_rawDescData = file_github_com_openconfig_gnmi_proto_collector_collector_proto_rawDesc
+	file_github_com_openconfig_gnmi_proto_collector_collector_proto_rawDescData []byte
 )
 
 func file_github_com_openconfig_gnmi_proto_collector_collector_proto_rawDescGZIP() []byte {
 	file_github_com_openconfig_gnmi_proto_collector_collector_proto_rawDescOnce.Do(func() {
-		file_github_com_openconfig_gnmi_proto_collector_collector_proto_rawDescData = protoimpl.X.CompressGZIP(file_github_com_openconfig_gnmi_proto_collector_collector_proto_rawDescData)
+		file_github_com_openconfig_gnmi_proto_collector_collector_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_github_com_openconfig_gnmi_proto_collector_collector_proto_rawDesc), len(file_github_com_openconfig_gnmi_proto_collector_collector_proto_rawDesc)))
 	})
 	return file_github_com_openconfig_gnmi_proto_collector_collector_proto_rawDescData
 }
@@ -173,7 +173,7 @@ func file_github_com_openconfig_gnmi_proto_collector_collector_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_github_com_openconfig_gnmi_proto_collector_collector_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_github_com_openconfig_gnmi_proto_collector_collector_proto_rawDesc), len(file_github_com_openconfig_gnmi_proto_collector_collector_proto_rawDesc)),
 			NumEnums:      0,
 			NumMessages:   2,
 			NumExtensions: 0,
@@ -184,7 +184,6 @@ func file_github_com_openconfig_gnmi_proto_collector_collector_proto_init() {
 		MessageInfos:      file_github_com_openconfig_gnmi_proto_collector_collector_proto_msgTypes,
 	}.Build()
 	File_github_com_openconfig_gnmi_proto_collector_collector_proto = out.File
-	file_github_com_openconfig_gnmi_proto_collector_collector_proto_rawDesc = nil
 	file_github_com_openconfig_gnmi_proto_collector_collector_proto_goTypes = nil
 	file_github_com_openconfig_gnmi_proto_collector_collector_proto_depIdxs = nil
 }
diff --git a/api/go/github.com/openconfig/gnmi/proto/gnmi/gnmi.pb.go b/api/go/github.com/openconfig/gnmi/proto/gnmi/gnmi.pb.go
index d0162888f..0d1e241b0 100755
--- a/api/go/github.com/openconfig/gnmi/proto/gnmi/gnmi.pb.go
+++ b/api/go/github.com/openconfig/gnmi/proto/gnmi/gnmi.pb.go
@@ -16,7 +16,7 @@
 
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: github.com/openconfig/gnmi/proto/gnmi/gnmi.proto
 
@@ -39,6 +39,7 @@ import (
 	anypb "google.golang.org/protobuf/types/known/anypb"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -329,12 +330,9 @@ func (GetRequest_DataType) EnumDescriptor() ([]byte, []int) {
 //
 // Reference: gNMI Specification Section 2.1
 type Notification struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Prefix    *Path `protobuf:"bytes,2,opt,name=prefix,proto3" json:"prefix,omitempty"`        // Prefix used for paths in the message.
+	state     protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Prefix    *Path                  `protobuf:"bytes,2,opt,name=prefix,proto3" json:"prefix,omitempty"`        // Prefix used for paths in the message.
 	// An alias for the path specified in the prefix field.
 	// Reference: gNMI Specification Section 2.4.2
 	Alias  string    `protobuf:"bytes,3,opt,name=alias,proto3" json:"alias,omitempty"`
@@ -342,7 +340,9 @@ type Notification struct {
 	Delete []*Path   `protobuf:"bytes,5,rep,name=delete,proto3" json:"delete,omitempty"` // Data elements that have been deleted.
 	// This notification contains a set of paths that are always updated together
 	// referenced by a globally unique prefix.
-	Atomic bool `protobuf:"varint,6,opt,name=atomic,proto3" json:"atomic,omitempty"`
+	Atomic        bool `protobuf:"varint,6,opt,name=atomic,proto3" json:"atomic,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Notification) Reset() {
@@ -421,15 +421,14 @@ func (x *Notification) GetAtomic() bool {
 // Value pair.
 // Reference: gNMI Specification Section 2.1
 type Update struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Path *Path `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` // The path (key) for the update.
+	state protoimpl.MessageState `protogen:"open.v1"`
+	Path  *Path                  `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` // The path (key) for the update.
 	// Deprecated: Marked as deprecated in github.com/openconfig/gnmi/proto/gnmi/gnmi.proto.
-	Value      *Value      `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`            // The value (value) for the update.
-	Val        *TypedValue `protobuf:"bytes,3,opt,name=val,proto3" json:"val,omitempty"`                // The explicitly typed update value.
-	Duplicates uint32      `protobuf:"varint,4,opt,name=duplicates,proto3" json:"duplicates,omitempty"` // Number of coalesced duplicates.
+	Value         *Value      `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`            // The value (value) for the update.
+	Val           *TypedValue `protobuf:"bytes,3,opt,name=val,proto3" json:"val,omitempty"`                // The explicitly typed update value.
+	Duplicates    uint32      `protobuf:"varint,4,opt,name=duplicates,proto3" json:"duplicates,omitempty"` // Number of coalesced duplicates.
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Update) Reset() {
@@ -494,17 +493,14 @@ func (x *Update) GetDuplicates() uint32 {
 // TypedValue is used to encode a value being sent between the client and
 // target (originated by either entity).
 type TypedValue struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// One of the fields within the val oneof is populated with the value
 	// of the update. The type of the value being included in the Update
 	// determines which field should be populated. In the case that the
 	// encoding is a particular form of the base protobuf type, a specific
 	// field is used to store the value (e.g., json_val).
 	//
-	// Types that are assignable to Value:
+	// Types that are valid to be assigned to Value:
 	//
 	//	*TypedValue_StringVal
 	//	*TypedValue_IntVal
@@ -519,7 +515,9 @@ type TypedValue struct {
 	//	*TypedValue_JsonIetfVal
 	//	*TypedValue_AsciiVal
 	//	*TypedValue_ProtoBytes
-	Value isTypedValue_Value `protobuf_oneof:"value"`
+	Value         isTypedValue_Value `protobuf_oneof:"value"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *TypedValue) Reset() {
@@ -552,100 +550,126 @@ func (*TypedValue) Descriptor() ([]byte, []int) {
 	return file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDescGZIP(), []int{2}
 }
 
-func (m *TypedValue) GetValue() isTypedValue_Value {
-	if m != nil {
-		return m.Value
+func (x *TypedValue) GetValue() isTypedValue_Value {
+	if x != nil {
+		return x.Value
 	}
 	return nil
 }
 
 func (x *TypedValue) GetStringVal() string {
-	if x, ok := x.GetValue().(*TypedValue_StringVal); ok {
-		return x.StringVal
+	if x != nil {
+		if x, ok := x.Value.(*TypedValue_StringVal); ok {
+			return x.StringVal
+		}
 	}
 	return ""
 }
 
 func (x *TypedValue) GetIntVal() int64 {
-	if x, ok := x.GetValue().(*TypedValue_IntVal); ok {
-		return x.IntVal
+	if x != nil {
+		if x, ok := x.Value.(*TypedValue_IntVal); ok {
+			return x.IntVal
+		}
 	}
 	return 0
 }
 
 func (x *TypedValue) GetUintVal() uint64 {
-	if x, ok := x.GetValue().(*TypedValue_UintVal); ok {
-		return x.UintVal
+	if x != nil {
+		if x, ok := x.Value.(*TypedValue_UintVal); ok {
+			return x.UintVal
+		}
 	}
 	return 0
 }
 
 func (x *TypedValue) GetBoolVal() bool {
-	if x, ok := x.GetValue().(*TypedValue_BoolVal); ok {
-		return x.BoolVal
+	if x != nil {
+		if x, ok := x.Value.(*TypedValue_BoolVal); ok {
+			return x.BoolVal
+		}
 	}
 	return false
 }
 
 func (x *TypedValue) GetBytesVal() []byte {
-	if x, ok := x.GetValue().(*TypedValue_BytesVal); ok {
-		return x.BytesVal
+	if x != nil {
+		if x, ok := x.Value.(*TypedValue_BytesVal); ok {
+			return x.BytesVal
+		}
 	}
 	return nil
 }
 
 func (x *TypedValue) GetFloatVal() float32 {
-	if x, ok := x.GetValue().(*TypedValue_FloatVal); ok {
-		return x.FloatVal
+	if x != nil {
+		if x, ok := x.Value.(*TypedValue_FloatVal); ok {
+			return x.FloatVal
+		}
 	}
 	return 0
 }
 
 func (x *TypedValue) GetDecimalVal() *Decimal64 {
-	if x, ok := x.GetValue().(*TypedValue_DecimalVal); ok {
-		return x.DecimalVal
+	if x != nil {
+		if x, ok := x.Value.(*TypedValue_DecimalVal); ok {
+			return x.DecimalVal
+		}
 	}
 	return nil
 }
 
 func (x *TypedValue) GetLeaflistVal() *ScalarArray {
-	if x, ok := x.GetValue().(*TypedValue_LeaflistVal); ok {
-		return x.LeaflistVal
+	if x != nil {
+		if x, ok := x.Value.(*TypedValue_LeaflistVal); ok {
+			return x.LeaflistVal
+		}
 	}
 	return nil
 }
 
 func (x *TypedValue) GetAnyVal() *anypb.Any {
-	if x, ok := x.GetValue().(*TypedValue_AnyVal); ok {
-		return x.AnyVal
+	if x != nil {
+		if x, ok := x.Value.(*TypedValue_AnyVal); ok {
+			return x.AnyVal
+		}
 	}
 	return nil
 }
 
 func (x *TypedValue) GetJsonVal() []byte {
-	if x, ok := x.GetValue().(*TypedValue_JsonVal); ok {
-		return x.JsonVal
+	if x != nil {
+		if x, ok := x.Value.(*TypedValue_JsonVal); ok {
+			return x.JsonVal
+		}
 	}
 	return nil
 }
 
 func (x *TypedValue) GetJsonIetfVal() []byte {
-	if x, ok := x.GetValue().(*TypedValue_JsonIetfVal); ok {
-		return x.JsonIetfVal
+	if x != nil {
+		if x, ok := x.Value.(*TypedValue_JsonIetfVal); ok {
+			return x.JsonIetfVal
+		}
 	}
 	return nil
 }
 
 func (x *TypedValue) GetAsciiVal() string {
-	if x, ok := x.GetValue().(*TypedValue_AsciiVal); ok {
-		return x.AsciiVal
+	if x != nil {
+		if x, ok := x.Value.(*TypedValue_AsciiVal); ok {
+			return x.AsciiVal
+		}
 	}
 	return ""
 }
 
 func (x *TypedValue) GetProtoBytes() []byte {
-	if x, ok := x.GetValue().(*TypedValue_ProtoBytes); ok {
-		return x.ProtoBytes
+	if x != nil {
+		if x, ok := x.Value.(*TypedValue_ProtoBytes); ok {
+			return x.ProtoBytes
+		}
 	}
 	return nil
 }
@@ -741,18 +765,17 @@ func (*TypedValue_ProtoBytes) isTypedValue_Value() {}
 // associated attributes.
 // Reference: gNMI Specification Section 2.2.2.
 type Path struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// Elements of the path are no longer encoded as a string, but rather within
 	// the elem field as a PathElem message.
 	//
 	// Deprecated: Marked as deprecated in github.com/openconfig/gnmi/proto/gnmi/gnmi.proto.
-	Element []string    `protobuf:"bytes,1,rep,name=element,proto3" json:"element,omitempty"`
-	Origin  string      `protobuf:"bytes,2,opt,name=origin,proto3" json:"origin,omitempty"` // Label to disambiguate path.
-	Elem    []*PathElem `protobuf:"bytes,3,rep,name=elem,proto3" json:"elem,omitempty"`     // Elements of the path.
-	Target  string      `protobuf:"bytes,4,opt,name=target,proto3" json:"target,omitempty"` // The name of the target
+	Element       []string    `protobuf:"bytes,1,rep,name=element,proto3" json:"element,omitempty"`
+	Origin        string      `protobuf:"bytes,2,opt,name=origin,proto3" json:"origin,omitempty"` // Label to disambiguate path.
+	Elem          []*PathElem `protobuf:"bytes,3,rep,name=elem,proto3" json:"elem,omitempty"`     // Elements of the path.
+	Target        string      `protobuf:"bytes,4,opt,name=target,proto3" json:"target,omitempty"` // The name of the target
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Path) Reset() {
@@ -818,12 +841,11 @@ func (x *Path) GetTarget() string {
 // that may be associated with it.
 // Reference: gNMI Specification Section 2.2.2.
 type PathElem struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Name          string                 `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`                                                                         // The name of the element in the path.
+	Key           map[string]string      `protobuf:"bytes,2,rep,name=key,proto3" json:"key,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // Map of key (attribute) name to value.
 	unknownFields protoimpl.UnknownFields
-
-	Name string            `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`                                                                                       // The name of the element in the path.
-	Key  map[string]string `protobuf:"bytes,2,rep,name=key,proto3" json:"key,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // Map of key (attribute) name to value.
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *PathElem) Reset() {
@@ -876,12 +898,11 @@ func (x *PathElem) GetKey() map[string]string {
 //
 // Deprecated: Marked as deprecated in github.com/openconfig/gnmi/proto/gnmi/gnmi.proto.
 type Value struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Value         []byte                 `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`                   // Value of the variable being transmitted.
+	Type          Encoding               `protobuf:"varint,2,opt,name=type,proto3,enum=gnmi.Encoding" json:"type,omitempty"` // Encoding used for the value field.
 	unknownFields protoimpl.UnknownFields
-
-	Value []byte   `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`                   // Value of the variable being transmitted.
-	Type  Encoding `protobuf:"varint,2,opt,name=type,proto3,enum=gnmi.Encoding" json:"type,omitempty"` // Encoding used for the value field.
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Value) Reset() {
@@ -935,13 +956,12 @@ func (x *Value) GetType() Encoding {
 //
 // Deprecated: Marked as deprecated in github.com/openconfig/gnmi/proto/gnmi/gnmi.proto.
 type Error struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Code          uint32                 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`      // Canonical gRPC error code.
+	Message       string                 `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` // Human readable error.
+	Data          *anypb.Any             `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"`       // Optional additional information.
 	unknownFields protoimpl.UnknownFields
-
-	Code    uint32     `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`      // Canonical gRPC error code.
-	Message string     `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` // Human readable error.
-	Data    *anypb.Any `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"`       // Optional additional information.
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Error) Reset() {
@@ -999,12 +1019,11 @@ func (x *Error) GetData() *anypb.Any {
 // is expressed as a set of digits with the precision specifying the
 // number of digits following the decimal point in the digit set.
 type Decimal64 struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Digits        int64                  `protobuf:"varint,1,opt,name=digits,proto3" json:"digits,omitempty"`       // Set of digits.
+	Precision     uint32                 `protobuf:"varint,2,opt,name=precision,proto3" json:"precision,omitempty"` // Number of digits following the decimal point.
 	unknownFields protoimpl.UnknownFields
-
-	Digits    int64  `protobuf:"varint,1,opt,name=digits,proto3" json:"digits,omitempty"`       // Set of digits.
-	Precision uint32 `protobuf:"varint,2,opt,name=precision,proto3" json:"precision,omitempty"` // Number of digits following the decimal point.
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Decimal64) Reset() {
@@ -1053,14 +1072,13 @@ func (x *Decimal64) GetPrecision() uint32 {
 
 // ScalarArray is used to encode a mixed-type array of values.
 type ScalarArray struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// The set of elements within the array. Each TypedValue message should
 	// specify only elements that have a field identifier of 1-7 (i.e., the
 	// values are scalar values).
-	Element []*TypedValue `protobuf:"bytes,1,rep,name=element,proto3" json:"element,omitempty"`
+	Element       []*TypedValue `protobuf:"bytes,1,rep,name=element,proto3" json:"element,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *ScalarArray) Reset() {
@@ -1107,11 +1125,8 @@ func (x *ScalarArray) GetElement() []*TypedValue {
 // used to define aliases or trigger polled data to be sent by the target.
 // Reference: gNMI Specification Section 3.5.1.1
 type SubscribeRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Types that are assignable to Request:
+	state protoimpl.MessageState `protogen:"open.v1"`
+	// Types that are valid to be assigned to Request:
 	//
 	//	*SubscribeRequest_Subscribe
 	//	*SubscribeRequest_Poll
@@ -1119,7 +1134,9 @@ type SubscribeRequest struct {
 	Request isSubscribeRequest_Request `protobuf_oneof:"request"`
 	// Extension messages associated with the SubscribeRequest. See the
 	// gNMI extension specification for further definition.
-	Extension []*gnmi_ext.Extension `protobuf:"bytes,5,rep,name=extension,proto3" json:"extension,omitempty"`
+	Extension     []*gnmi_ext.Extension `protobuf:"bytes,5,rep,name=extension,proto3" json:"extension,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *SubscribeRequest) Reset() {
@@ -1152,30 +1169,36 @@ func (*SubscribeRequest) Descriptor() ([]byte, []int) {
 	return file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDescGZIP(), []int{9}
 }
 
-func (m *SubscribeRequest) GetRequest() isSubscribeRequest_Request {
-	if m != nil {
-		return m.Request
+func (x *SubscribeRequest) GetRequest() isSubscribeRequest_Request {
+	if x != nil {
+		return x.Request
 	}
 	return nil
 }
 
 func (x *SubscribeRequest) GetSubscribe() *SubscriptionList {
-	if x, ok := x.GetRequest().(*SubscribeRequest_Subscribe); ok {
-		return x.Subscribe
+	if x != nil {
+		if x, ok := x.Request.(*SubscribeRequest_Subscribe); ok {
+			return x.Subscribe
+		}
 	}
 	return nil
 }
 
 func (x *SubscribeRequest) GetPoll() *Poll {
-	if x, ok := x.GetRequest().(*SubscribeRequest_Poll); ok {
-		return x.Poll
+	if x != nil {
+		if x, ok := x.Request.(*SubscribeRequest_Poll); ok {
+			return x.Poll
+		}
 	}
 	return nil
 }
 
 func (x *SubscribeRequest) GetAliases() *AliasList {
-	if x, ok := x.GetRequest().(*SubscribeRequest_Aliases); ok {
-		return x.Aliases
+	if x != nil {
+		if x, ok := x.Request.(*SubscribeRequest_Aliases); ok {
+			return x.Aliases
+		}
 	}
 	return nil
 }
@@ -1214,9 +1237,9 @@ func (*SubscribeRequest_Aliases) isSubscribeRequest_Request() {}
 // subscription.
 // Reference: gNMI Specification Section Section 3.5.1.4
 type Poll struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
 	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Poll) Reset() {
@@ -1256,11 +1279,8 @@ func (*Poll) Descriptor() ([]byte, []int) {
 // synchronized).
 // Reference: gNMI Specification Section 3.5.1.4
 type SubscribeResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Types that are assignable to Response:
+	state protoimpl.MessageState `protogen:"open.v1"`
+	// Types that are valid to be assigned to Response:
 	//
 	//	*SubscribeResponse_Update
 	//	*SubscribeResponse_SyncResponse
@@ -1268,7 +1288,9 @@ type SubscribeResponse struct {
 	Response isSubscribeResponse_Response `protobuf_oneof:"response"`
 	// Extension messages associated with the SubscribeResponse. See the
 	// gNMI extension specification for further definition.
-	Extension []*gnmi_ext.Extension `protobuf:"bytes,5,rep,name=extension,proto3" json:"extension,omitempty"`
+	Extension     []*gnmi_ext.Extension `protobuf:"bytes,5,rep,name=extension,proto3" json:"extension,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *SubscribeResponse) Reset() {
@@ -1301,31 +1323,37 @@ func (*SubscribeResponse) Descriptor() ([]byte, []int) {
 	return file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDescGZIP(), []int{11}
 }
 
-func (m *SubscribeResponse) GetResponse() isSubscribeResponse_Response {
-	if m != nil {
-		return m.Response
+func (x *SubscribeResponse) GetResponse() isSubscribeResponse_Response {
+	if x != nil {
+		return x.Response
 	}
 	return nil
 }
 
 func (x *SubscribeResponse) GetUpdate() *Notification {
-	if x, ok := x.GetResponse().(*SubscribeResponse_Update); ok {
-		return x.Update
+	if x != nil {
+		if x, ok := x.Response.(*SubscribeResponse_Update); ok {
+			return x.Update
+		}
 	}
 	return nil
 }
 
 func (x *SubscribeResponse) GetSyncResponse() bool {
-	if x, ok := x.GetResponse().(*SubscribeResponse_SyncResponse); ok {
-		return x.SyncResponse
+	if x != nil {
+		if x, ok := x.Response.(*SubscribeResponse_SyncResponse); ok {
+			return x.SyncResponse
+		}
 	}
 	return false
 }
 
 // Deprecated: Marked as deprecated in github.com/openconfig/gnmi/proto/gnmi/gnmi.proto.
 func (x *SubscribeResponse) GetError() *Error {
-	if x, ok := x.GetResponse().(*SubscribeResponse_Error); ok {
-		return x.Error
+	if x != nil {
+		if x, ok := x.Response.(*SubscribeResponse_Error); ok {
+			return x.Error
+		}
 	}
 	return nil
 }
@@ -1370,12 +1398,9 @@ func (*SubscribeResponse_Error) isSubscribeResponse_Response() {}
 // subscription.
 // Reference: gNMI Specification Section 3.5.1.2
 type SubscriptionList struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Prefix       *Path           `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"`             // Prefix used for paths.
-	Subscription []*Subscription `protobuf:"bytes,2,rep,name=subscription,proto3" json:"subscription,omitempty"` // Set of subscriptions to create.
+	state        protoimpl.MessageState `protogen:"open.v1"`
+	Prefix       *Path                  `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"`             // Prefix used for paths.
+	Subscription []*Subscription        `protobuf:"bytes,2,rep,name=subscription,proto3" json:"subscription,omitempty"` // Set of subscriptions to create.
 	// Whether target defined aliases are allowed within the subscription.
 	UseAliases bool                  `protobuf:"varint,3,opt,name=use_aliases,json=useAliases,proto3" json:"use_aliases,omitempty"`
 	Qos        *QOSMarking           `protobuf:"bytes,4,opt,name=qos,proto3" json:"qos,omitempty"` // DSCP marking to be used.
@@ -1394,7 +1419,9 @@ type SubscriptionList struct {
 	// rather only the sync message followed by any subsequent updates to the
 	// current state. For ONCE and POLL modes, this causes the server to send only
 	// the sync message (Sec. 3.5.2.3).
-	UpdatesOnly bool `protobuf:"varint,9,opt,name=updates_only,json=updatesOnly,proto3" json:"updates_only,omitempty"`
+	UpdatesOnly   bool `protobuf:"varint,9,opt,name=updates_only,json=updatesOnly,proto3" json:"updates_only,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *SubscriptionList) Reset() {
@@ -1496,13 +1523,10 @@ func (x *SubscriptionList) GetUpdatesOnly() bool {
 // should trigger updates to be sent.
 // Reference: gNMI Specification Section 3.5.1.3
 type Subscription struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Path           *Path            `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`                                            // The data tree path.
-	Mode           SubscriptionMode `protobuf:"varint,2,opt,name=mode,proto3,enum=gnmi.SubscriptionMode" json:"mode,omitempty"`                // Subscription mode to be used.
-	SampleInterval uint64           `protobuf:"varint,3,opt,name=sample_interval,json=sampleInterval,proto3" json:"sample_interval,omitempty"` // ns between samples in SAMPLE mode.
+	state          protoimpl.MessageState `protogen:"open.v1"`
+	Path           *Path                  `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`                                            // The data tree path.
+	Mode           SubscriptionMode       `protobuf:"varint,2,opt,name=mode,proto3,enum=gnmi.SubscriptionMode" json:"mode,omitempty"`                // Subscription mode to be used.
+	SampleInterval uint64                 `protobuf:"varint,3,opt,name=sample_interval,json=sampleInterval,proto3" json:"sample_interval,omitempty"` // ns between samples in SAMPLE mode.
 	// Indicates whether values that have not changed should be sent in a SAMPLE
 	// subscription.
 	SuppressRedundant bool `protobuf:"varint,4,opt,name=suppress_redundant,json=suppressRedundant,proto3" json:"suppress_redundant,omitempty"`
@@ -1510,6 +1534,8 @@ type Subscription struct {
 	// suppress_redundant is in use. The target should send a value at least once
 	// in the period specified.
 	HeartbeatInterval uint64 `protobuf:"varint,5,opt,name=heartbeat_interval,json=heartbeatInterval,proto3" json:"heartbeat_interval,omitempty"`
+	unknownFields     protoimpl.UnknownFields
+	sizeCache         protoimpl.SizeCache
 }
 
 func (x *Subscription) Reset() {
@@ -1581,11 +1607,10 @@ func (x *Subscription) GetHeartbeatInterval() uint64 {
 // updates from the target.
 // Reference: gNMI Specification Section 3.5.1.2
 type QOSMarking struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Marking       uint32                 `protobuf:"varint,1,opt,name=marking,proto3" json:"marking,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Marking uint32 `protobuf:"varint,1,opt,name=marking,proto3" json:"marking,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *QOSMarking) Reset() {
@@ -1631,12 +1656,11 @@ func (x *QOSMarking) GetMarking() uint32 {
 // data tree element paths.
 // Reference: gNMI Specification Section 2.4.2
 type Alias struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Path          *Path                  `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`   // The path to be aliased.
+	Alias         string                 `protobuf:"bytes,2,opt,name=alias,proto3" json:"alias,omitempty"` // The alias value, a string prefixed by "#".
 	unknownFields protoimpl.UnknownFields
-
-	Path  *Path  `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`   // The path to be aliased.
-	Alias string `protobuf:"bytes,2,opt,name=alias,proto3" json:"alias,omitempty"` // The alias value, a string prefixed by "#".
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Alias) Reset() {
@@ -1687,11 +1711,10 @@ func (x *Alias) GetAlias() string {
 // a client to create a set of aliases that the target is to utilize.
 // Reference: gNMI Specification Section 3.5.1.6
 type AliasList struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Alias         []*Alias               `protobuf:"bytes,1,rep,name=alias,proto3" json:"alias,omitempty"` // The set of aliases to be created.
 	unknownFields protoimpl.UnknownFields
-
-	Alias []*Alias `protobuf:"bytes,1,rep,name=alias,proto3" json:"alias,omitempty"` // The set of aliases to be created.
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *AliasList) Reset() {
@@ -1739,17 +1762,16 @@ func (x *AliasList) GetAlias() []*Alias {
 // a single SetRequest are considered to be a transaction.
 // Reference: gNMI Specification Section 3.4.1
 type SetRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Prefix  *Path     `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"`   // Prefix used for paths in the message.
-	Delete  []*Path   `protobuf:"bytes,2,rep,name=delete,proto3" json:"delete,omitempty"`   // Paths to be deleted from the data tree.
-	Replace []*Update `protobuf:"bytes,3,rep,name=replace,proto3" json:"replace,omitempty"` // Updates specifying elements to be replaced.
-	Update  []*Update `protobuf:"bytes,4,rep,name=update,proto3" json:"update,omitempty"`   // Updates specifying elements to updated.
+	state   protoimpl.MessageState `protogen:"open.v1"`
+	Prefix  *Path                  `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"`   // Prefix used for paths in the message.
+	Delete  []*Path                `protobuf:"bytes,2,rep,name=delete,proto3" json:"delete,omitempty"`   // Paths to be deleted from the data tree.
+	Replace []*Update              `protobuf:"bytes,3,rep,name=replace,proto3" json:"replace,omitempty"` // Updates specifying elements to be replaced.
+	Update  []*Update              `protobuf:"bytes,4,rep,name=update,proto3" json:"update,omitempty"`   // Updates specifying elements to updated.
 	// Extension messages associated with the SetRequest. See the
 	// gNMI extension specification for further definition.
-	Extension []*gnmi_ext.Extension `protobuf:"bytes,5,rep,name=extension,proto3" json:"extension,omitempty"`
+	Extension     []*gnmi_ext.Extension `protobuf:"bytes,5,rep,name=extension,proto3" json:"extension,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *SetRequest) Reset() {
@@ -1825,11 +1847,8 @@ func (x *SetRequest) GetExtension() []*gnmi_ext.Extension {
 // details where required.
 // Reference: gNMI Specification Section 3.4.2
 type SetResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Prefix *Path `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"` // Prefix used for paths.
+	state  protoimpl.MessageState `protogen:"open.v1"`
+	Prefix *Path                  `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"` // Prefix used for paths.
 	// A set of responses specifying the result of the operations specified in
 	// the SetRequest.
 	Response []*UpdateResult `protobuf:"bytes,2,rep,name=response,proto3" json:"response,omitempty"`
@@ -1838,7 +1857,9 @@ type SetResponse struct {
 	Timestamp int64  `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp of transaction (ns since epoch).
 	// Extension messages associated with the SetResponse. See the
 	// gNMI extension specification for further definition.
-	Extension []*gnmi_ext.Extension `protobuf:"bytes,5,rep,name=extension,proto3" json:"extension,omitempty"`
+	Extension     []*gnmi_ext.Extension `protobuf:"bytes,5,rep,name=extension,proto3" json:"extension,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *SetResponse) Reset() {
@@ -1911,10 +1932,7 @@ func (x *SetResponse) GetExtension() []*gnmi_ext.Extension {
 // result of an operation specified within a SetRequest message.
 // Reference: gNMI Specification Section 3.4.2
 type UpdateResult struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// Deprecated timestamp for the UpdateResult, this field has been
 	// replaced by the timestamp within the SetResponse message, since
 	// all mutations effected by a set should be applied as a single
@@ -1924,8 +1942,10 @@ type UpdateResult struct {
 	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	Path      *Path `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"` // Path associated with the update.
 	// Deprecated: Marked as deprecated in github.com/openconfig/gnmi/proto/gnmi/gnmi.proto.
-	Message *Error                 `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"`                         // Status of the update operation.
-	Op      UpdateResult_Operation `protobuf:"varint,4,opt,name=op,proto3,enum=gnmi.UpdateResult_Operation" json:"op,omitempty"` // Update operation type.
+	Message       *Error                 `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"`                         // Status of the update operation.
+	Op            UpdateResult_Operation `protobuf:"varint,4,opt,name=op,proto3,enum=gnmi.UpdateResult_Operation" json:"op,omitempty"` // Update operation type.
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *UpdateResult) Reset() {
@@ -1995,18 +2015,17 @@ func (x *UpdateResult) GetOp() UpdateResult_Operation {
 // must use all schema models that it has.
 // Reference: gNMI Specification Section 3.3.1
 type GetRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Prefix    *Path               `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"`                            // Prefix used for paths.
-	Path      []*Path             `protobuf:"bytes,2,rep,name=path,proto3" json:"path,omitempty"`                                // Paths requested by the client.
-	Type      GetRequest_DataType `protobuf:"varint,3,opt,name=type,proto3,enum=gnmi.GetRequest_DataType" json:"type,omitempty"` // The type of data being requested.
-	Encoding  Encoding            `protobuf:"varint,5,opt,name=encoding,proto3,enum=gnmi.Encoding" json:"encoding,omitempty"`    // Encoding to be used.
-	UseModels []*ModelData        `protobuf:"bytes,6,rep,name=use_models,json=useModels,proto3" json:"use_models,omitempty"`     // The schema models to be used.
+	state     protoimpl.MessageState `protogen:"open.v1"`
+	Prefix    *Path                  `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"`                            // Prefix used for paths.
+	Path      []*Path                `protobuf:"bytes,2,rep,name=path,proto3" json:"path,omitempty"`                                // Paths requested by the client.
+	Type      GetRequest_DataType    `protobuf:"varint,3,opt,name=type,proto3,enum=gnmi.GetRequest_DataType" json:"type,omitempty"` // The type of data being requested.
+	Encoding  Encoding               `protobuf:"varint,5,opt,name=encoding,proto3,enum=gnmi.Encoding" json:"encoding,omitempty"`    // Encoding to be used.
+	UseModels []*ModelData           `protobuf:"bytes,6,rep,name=use_models,json=useModels,proto3" json:"use_models,omitempty"`     // The schema models to be used.
 	// Extension messages associated with the GetRequest. See the
 	// gNMI extension specification for further definition.
-	Extension []*gnmi_ext.Extension `protobuf:"bytes,7,rep,name=extension,proto3" json:"extension,omitempty"`
+	Extension     []*gnmi_ext.Extension `protobuf:"bytes,7,rep,name=extension,proto3" json:"extension,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetRequest) Reset() {
@@ -2086,16 +2105,15 @@ func (x *GetRequest) GetExtension() []*gnmi_ext.Extension {
 // by the client in the GetRequest.
 // Reference: gNMI Specification Section 3.3.2
 type GetResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Notification []*Notification `protobuf:"bytes,1,rep,name=notification,proto3" json:"notification,omitempty"` // Data values.
+	state        protoimpl.MessageState `protogen:"open.v1"`
+	Notification []*Notification        `protobuf:"bytes,1,rep,name=notification,proto3" json:"notification,omitempty"` // Data values.
 	// Deprecated: Marked as deprecated in github.com/openconfig/gnmi/proto/gnmi/gnmi.proto.
 	Error *Error `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` // Errors that occurred in the Get.
 	// Extension messages associated with the GetResponse. See the
 	// gNMI extension specification for further definition.
-	Extension []*gnmi_ext.Extension `protobuf:"bytes,3,rep,name=extension,proto3" json:"extension,omitempty"`
+	Extension     []*gnmi_ext.Extension `protobuf:"bytes,3,rep,name=extension,proto3" json:"extension,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetResponse) Reset() {
@@ -2154,13 +2172,12 @@ func (x *GetResponse) GetExtension() []*gnmi_ext.Extension {
 // that the target reports its capabilities.
 // Reference: gNMI Specification Section 3.2.1
 type CapabilityRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// Extension messages associated with the CapabilityRequest. See the
 	// gNMI extension specification for further definition.
-	Extension []*gnmi_ext.Extension `protobuf:"bytes,1,rep,name=extension,proto3" json:"extension,omitempty"`
+	Extension     []*gnmi_ext.Extension `protobuf:"bytes,1,rep,name=extension,proto3" json:"extension,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *CapabilityRequest) Reset() {
@@ -2204,16 +2221,15 @@ func (x *CapabilityRequest) GetExtension() []*gnmi_ext.Extension {
 // client within the Capabilities RPC.
 // Reference: gNMI Specification Section 3.2.2
 type CapabilityResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	SupportedModels    []*ModelData `protobuf:"bytes,1,rep,name=supported_models,json=supportedModels,proto3" json:"supported_models,omitempty"`                                     // Supported schema models.
-	SupportedEncodings []Encoding   `protobuf:"varint,2,rep,packed,name=supported_encodings,json=supportedEncodings,proto3,enum=gnmi.Encoding" json:"supported_encodings,omitempty"` // Supported encodings.
-	GNMIVersion        string       `protobuf:"bytes,3,opt,name=gNMI_version,json=gNMIVersion,proto3" json:"gNMI_version,omitempty"`                                                 // Supported gNMI version.
+	state              protoimpl.MessageState `protogen:"open.v1"`
+	SupportedModels    []*ModelData           `protobuf:"bytes,1,rep,name=supported_models,json=supportedModels,proto3" json:"supported_models,omitempty"`                                     // Supported schema models.
+	SupportedEncodings []Encoding             `protobuf:"varint,2,rep,packed,name=supported_encodings,json=supportedEncodings,proto3,enum=gnmi.Encoding" json:"supported_encodings,omitempty"` // Supported encodings.
+	GNMIVersion        string                 `protobuf:"bytes,3,opt,name=gNMI_version,json=gNMIVersion,proto3" json:"gNMI_version,omitempty"`                                                 // Supported gNMI version.
 	// Extension messages associated with the CapabilityResponse. See the
 	// gNMI extension specification for further definition.
-	Extension []*gnmi_ext.Extension `protobuf:"bytes,4,rep,name=extension,proto3" json:"extension,omitempty"`
+	Extension     []*gnmi_ext.Extension `protobuf:"bytes,4,rep,name=extension,proto3" json:"extension,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *CapabilityResponse) Reset() {
@@ -2280,13 +2296,12 @@ func (x *CapabilityResponse) GetExtension() []*gnmi_ext.Extension {
 // the set of models from which data tree elements should be reported.
 // Reference: gNMI Specification Section 3.2.3
 type ModelData struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Name          string                 `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`                 // Name of the model.
+	Organization  string                 `protobuf:"bytes,2,opt,name=organization,proto3" json:"organization,omitempty"` // Organization publishing the model.
+	Version       string                 `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"`           // Semantic version of the model.
 	unknownFields protoimpl.UnknownFields
-
-	Name         string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`                 // Name of the model.
-	Organization string `protobuf:"bytes,2,opt,name=organization,proto3" json:"organization,omitempty"` // Organization publishing the model.
-	Version      string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"`           // Semantic version of the model.
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *ModelData) Reset() {
@@ -2361,7 +2376,7 @@ var (
 
 var File_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto protoreflect.FileDescriptor
 
-var file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDesc = []byte{
+var file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDesc = string([]byte{
 	0x0a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65,
 	0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x67, 0x6e, 0x6d, 0x69, 0x2f, 0x70, 0x72, 0x6f,
 	0x74, 0x6f, 0x2f, 0x67, 0x6e, 0x6d, 0x69, 0x2f, 0x67, 0x6e, 0x6d, 0x69, 0x2e, 0x70, 0x72, 0x6f,
@@ -2671,16 +2686,16 @@ var file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDesc = []byte{
 	0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x67, 0x6e, 0x6d, 0x69,
 	0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6e, 0x6d, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f,
 	0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDescOnce sync.Once
-	file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDescData = file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDesc
+	file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDescData []byte
 )
 
 func file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDescGZIP() []byte {
 	file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDescOnce.Do(func() {
-		file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDescData = protoimpl.X.CompressGZIP(file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDescData)
+		file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDesc), len(file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDesc)))
 	})
 	return file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDescData
 }
@@ -2830,7 +2845,7 @@ func file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDesc), len(file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDesc)),
 			NumEnums:      5,
 			NumMessages:   26,
 			NumExtensions: 1,
@@ -2843,7 +2858,6 @@ func file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_init() {
 		ExtensionInfos:    file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_extTypes,
 	}.Build()
 	File_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto = out.File
-	file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_rawDesc = nil
 	file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_goTypes = nil
 	file_github_com_openconfig_gnmi_proto_gnmi_gnmi_proto_depIdxs = nil
 }
diff --git a/api/go/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.pb.go b/api/go/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.pb.go
index aaaa55d00..5536b80f4 100755
--- a/api/go/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.pb.go
+++ b/api/go/github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.pb.go
@@ -16,7 +16,7 @@
 
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: github.com/openconfig/gnmi/proto/gnmi_ext/gnmi_ext.proto
 
@@ -32,6 +32,7 @@ import (
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -93,16 +94,15 @@ func (ExtensionID) EnumDescriptor() ([]byte, []int) {
 
 // The Extension message contains a single gNMI extension.
 type Extension struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Types that are assignable to Ext:
+	state protoimpl.MessageState `protogen:"open.v1"`
+	// Types that are valid to be assigned to Ext:
 	//
 	//	*Extension_RegisteredExt
 	//	*Extension_MasterArbitration
 	//	*Extension_History
-	Ext isExtension_Ext `protobuf_oneof:"ext"`
+	Ext           isExtension_Ext `protobuf_oneof:"ext"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Extension) Reset() {
@@ -135,30 +135,36 @@ func (*Extension) Descriptor() ([]byte, []int) {
 	return file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_rawDescGZIP(), []int{0}
 }
 
-func (m *Extension) GetExt() isExtension_Ext {
-	if m != nil {
-		return m.Ext
+func (x *Extension) GetExt() isExtension_Ext {
+	if x != nil {
+		return x.Ext
 	}
 	return nil
 }
 
 func (x *Extension) GetRegisteredExt() *RegisteredExtension {
-	if x, ok := x.GetExt().(*Extension_RegisteredExt); ok {
-		return x.RegisteredExt
+	if x != nil {
+		if x, ok := x.Ext.(*Extension_RegisteredExt); ok {
+			return x.RegisteredExt
+		}
 	}
 	return nil
 }
 
 func (x *Extension) GetMasterArbitration() *MasterArbitration {
-	if x, ok := x.GetExt().(*Extension_MasterArbitration); ok {
-		return x.MasterArbitration
+	if x != nil {
+		if x, ok := x.Ext.(*Extension_MasterArbitration); ok {
+			return x.MasterArbitration
+		}
 	}
 	return nil
 }
 
 func (x *Extension) GetHistory() *History {
-	if x, ok := x.GetExt().(*Extension_History); ok {
-		return x.History
+	if x != nil {
+		if x, ok := x.Ext.(*Extension_History); ok {
+			return x.History
+		}
 	}
 	return nil
 }
@@ -189,12 +195,11 @@ func (*Extension_History) isExtension_Ext() {}
 // The RegisteredExtension message defines an extension which is defined outside
 // of this file.
 type RegisteredExtension struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Id            ExtensionID            `protobuf:"varint,1,opt,name=id,proto3,enum=gnmi_ext.ExtensionID" json:"id,omitempty"` // The unique ID assigned to this extension.
+	Msg           []byte                 `protobuf:"bytes,2,opt,name=msg,proto3" json:"msg,omitempty"`                          // The binary-marshalled protobuf extension payload.
 	unknownFields protoimpl.UnknownFields
-
-	Id  ExtensionID `protobuf:"varint,1,opt,name=id,proto3,enum=gnmi_ext.ExtensionID" json:"id,omitempty"` // The unique ID assigned to this extension.
-	Msg []byte      `protobuf:"bytes,2,opt,name=msg,proto3" json:"msg,omitempty"`                          // The binary-marshalled protobuf extension payload.
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *RegisteredExtension) Reset() {
@@ -247,12 +252,11 @@ func (x *RegisteredExtension) GetMsg() []byte {
 // The document about gNMI master arbitration can be found at
 // https://github.com/openconfig/reference/blob/master/rpc/gnmi/gnmi-master-arbitration.md
 type MasterArbitration struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Role          *Role                  `protobuf:"bytes,1,opt,name=role,proto3" json:"role,omitempty"`
+	ElectionId    *Uint128               `protobuf:"bytes,2,opt,name=election_id,json=electionId,proto3" json:"election_id,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Role       *Role    `protobuf:"bytes,1,opt,name=role,proto3" json:"role,omitempty"`
-	ElectionId *Uint128 `protobuf:"bytes,2,opt,name=election_id,json=electionId,proto3" json:"election_id,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *MasterArbitration) Reset() {
@@ -301,12 +305,11 @@ func (x *MasterArbitration) GetElectionId() *Uint128 {
 
 // Representation of unsigned 128-bit integer.
 type Uint128 struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	High          uint64                 `protobuf:"varint,1,opt,name=high,proto3" json:"high,omitempty"`
+	Low           uint64                 `protobuf:"varint,2,opt,name=low,proto3" json:"low,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	High uint64 `protobuf:"varint,1,opt,name=high,proto3" json:"high,omitempty"`
-	Low  uint64 `protobuf:"varint,2,opt,name=low,proto3" json:"low,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Uint128) Reset() {
@@ -355,11 +358,10 @@ func (x *Uint128) GetLow() uint64 {
 
 // There can be one master for each role. The role is identified by its id.
 type Role struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Id            string                 `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Role) Reset() {
@@ -403,15 +405,14 @@ func (x *Role) GetId() string {
 // spec can be found at
 // https://github.com/openconfig/reference/blob/master/rpc/gnmi/gnmi-history.md
 type History struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Types that are assignable to Request:
+	state protoimpl.MessageState `protogen:"open.v1"`
+	// Types that are valid to be assigned to Request:
 	//
 	//	*History_SnapshotTime
 	//	*History_Range
-	Request isHistory_Request `protobuf_oneof:"request"`
+	Request       isHistory_Request `protobuf_oneof:"request"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *History) Reset() {
@@ -444,23 +445,27 @@ func (*History) Descriptor() ([]byte, []int) {
 	return file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_rawDescGZIP(), []int{5}
 }
 
-func (m *History) GetRequest() isHistory_Request {
-	if m != nil {
-		return m.Request
+func (x *History) GetRequest() isHistory_Request {
+	if x != nil {
+		return x.Request
 	}
 	return nil
 }
 
 func (x *History) GetSnapshotTime() int64 {
-	if x, ok := x.GetRequest().(*History_SnapshotTime); ok {
-		return x.SnapshotTime
+	if x != nil {
+		if x, ok := x.Request.(*History_SnapshotTime); ok {
+			return x.SnapshotTime
+		}
 	}
 	return 0
 }
 
 func (x *History) GetRange() *TimeRange {
-	if x, ok := x.GetRequest().(*History_Range); ok {
-		return x.Range
+	if x != nil {
+		if x, ok := x.Request.(*History_Range); ok {
+			return x.Range
+		}
 	}
 	return nil
 }
@@ -482,12 +487,11 @@ func (*History_SnapshotTime) isHistory_Request() {}
 func (*History_Range) isHistory_Request() {}
 
 type TimeRange struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Start         int64                  `protobuf:"varint,1,opt,name=start,proto3" json:"start,omitempty"` // Nanoseconds since the epoch
+	End           int64                  `protobuf:"varint,2,opt,name=end,proto3" json:"end,omitempty"`     // Nanoseconds since the epoch
 	unknownFields protoimpl.UnknownFields
-
-	Start int64 `protobuf:"varint,1,opt,name=start,proto3" json:"start,omitempty"` // Nanoseconds since the epoch
-	End   int64 `protobuf:"varint,2,opt,name=end,proto3" json:"end,omitempty"`     // Nanoseconds since the epoch
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *TimeRange) Reset() {
@@ -536,7 +540,7 @@ func (x *TimeRange) GetEnd() int64 {
 
 var File_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto protoreflect.FileDescriptor
 
-var file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_rawDesc = []byte{
+var file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_rawDesc = string([]byte{
 	0x0a, 0x38, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65,
 	0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x67, 0x6e, 0x6d, 0x69, 0x2f, 0x70, 0x72, 0x6f,
 	0x74, 0x6f, 0x2f, 0x67, 0x6e, 0x6d, 0x69, 0x5f, 0x65, 0x78, 0x74, 0x2f, 0x67, 0x6e, 0x6d, 0x69,
@@ -588,16 +592,16 @@ var file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_rawDesc = []by
 	0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69,
 	0x67, 0x2f, 0x67, 0x6e, 0x6d, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6e, 0x6d,
 	0x69, 0x5f, 0x65, 0x78, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_rawDescOnce sync.Once
-	file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_rawDescData = file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_rawDesc
+	file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_rawDescData []byte
 )
 
 func file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_rawDescGZIP() []byte {
 	file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_rawDescOnce.Do(func() {
-		file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_rawDescData = protoimpl.X.CompressGZIP(file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_rawDescData)
+		file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_rawDesc), len(file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_rawDesc)))
 	})
 	return file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_rawDescData
 }
@@ -647,7 +651,7 @@ func file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_rawDesc), len(file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_rawDesc)),
 			NumEnums:      1,
 			NumMessages:   7,
 			NumExtensions: 0,
@@ -659,7 +663,6 @@ func file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_init() {
 		MessageInfos:      file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_msgTypes,
 	}.Build()
 	File_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto = out.File
-	file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_rawDesc = nil
 	file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_goTypes = nil
 	file_github_com_openconfig_gnmi_proto_gnmi_ext_gnmi_ext_proto_depIdxs = nil
 }
diff --git a/api/go/github.com/openconfig/gnmi/proto/target/target.pb.go b/api/go/github.com/openconfig/gnmi/proto/target/target.pb.go
index 168a726d8..607f004a9 100755
--- a/api/go/github.com/openconfig/gnmi/proto/target/target.pb.go
+++ b/api/go/github.com/openconfig/gnmi/proto/target/target.pb.go
@@ -16,7 +16,7 @@
 
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: github.com/openconfig/gnmi/proto/target/target.proto
 
@@ -31,6 +31,7 @@ import (
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -43,21 +44,18 @@ const (
 // Configuration holds all information necessary for a caching gNMI collector
 // to establish subscriptions to a list of gNMI targets.
 type Configuration struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// Request is a keyed list of all SubscriptionRequests that can be sent to
 	// to targets in the Configuration.
 	// The request must have at minimum a SubscriptionList with a prefix
 	// containing origin and one or more Subscriptions.  Only the STREAM mode is
 	// supported.
-	Request map[string]*gnmi.SubscribeRequest `protobuf:"bytes,1,rep,name=request,proto3" json:"request,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	Request map[string]*gnmi.SubscribeRequest `protobuf:"bytes,1,rep,name=request,proto3" json:"request,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
 	// Target is the full list of targets connected to by a caching gNMI
 	// collector.  The key of the map is a unique name to identify a target and
 	// is set in the prefix.target of a SubscriptionRequest message when connecting
 	// to each respective target.
-	Target map[string]*Target `protobuf:"bytes,2,rep,name=target,proto3" json:"target,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	Target map[string]*Target `protobuf:"bytes,2,rep,name=target,proto3" json:"target,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
 	// Identifier for the caching collector.
 	InstanceId string `protobuf:"bytes,3,opt,name=instance_id,json=instanceId,proto3" json:"instance_id,omitempty"`
 	// Revision for this Configuration. Systems that non-atomically write
@@ -65,7 +63,9 @@ type Configuration struct {
 	// protobuf serialization of fields in order. Presence of this field makes no
 	// guarantee. Consumers should account for atomicity constraints of their
 	// environment and any custom encoding.
-	Revision int64 `protobuf:"varint,536870911,opt,name=revision,proto3" json:"revision,omitempty"`
+	Revision      int64 `protobuf:"varint,536870911,opt,name=revision,proto3" json:"revision,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Configuration) Reset() {
@@ -129,10 +129,7 @@ func (x *Configuration) GetRevision() int64 {
 // Target is the information necessary to establish a single gNMI Subscribe RPC
 // to be collected and cached.
 type Target struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// A list of address and port or name that resolves to an address and port.
 	Addresses []string `protobuf:"bytes,1,rep,name=addresses,proto3" json:"addresses,omitempty"`
 	// Credentials to use in metadata for authorization of the RPC
@@ -141,7 +138,9 @@ type Target struct {
 	// the request map of the Configuration message.
 	Request string `protobuf:"bytes,3,opt,name=request,proto3" json:"request,omitempty"`
 	// Additional target metadata.
-	Meta map[string]string `protobuf:"bytes,4,rep,name=meta,proto3" json:"meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	Meta          map[string]string `protobuf:"bytes,4,rep,name=meta,proto3" json:"meta,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Target) Reset() {
@@ -205,14 +204,13 @@ func (x *Target) GetMeta() map[string]string {
 // Credentials contains the fields necessary for authentication of the client to
 // the target.
 type Credentials struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"`
-	Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
+	state    protoimpl.MessageState `protogen:"open.v1"`
+	Username string                 `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"`
+	Password string                 `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
 	// Password lookup ID.
-	PasswordId string `protobuf:"bytes,3,opt,name=password_id,json=passwordId,proto3" json:"password_id,omitempty"`
+	PasswordId    string `protobuf:"bytes,3,opt,name=password_id,json=passwordId,proto3" json:"password_id,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Credentials) Reset() {
@@ -268,7 +266,7 @@ func (x *Credentials) GetPasswordId() string {
 
 var File_github_com_openconfig_gnmi_proto_target_target_proto protoreflect.FileDescriptor
 
-var file_github_com_openconfig_gnmi_proto_target_target_proto_rawDesc = []byte{
+var file_github_com_openconfig_gnmi_proto_target_target_proto_rawDesc = string([]byte{
 	0x0a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65,
 	0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x67, 0x6e, 0x6d, 0x69, 0x2f, 0x70, 0x72, 0x6f,
 	0x74, 0x6f, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
@@ -323,16 +321,16 @@ var file_github_com_openconfig_gnmi_proto_target_target_proto_rawDesc = []byte{
 	0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x67, 0x6e,
 	0x6d, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x62,
 	0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_github_com_openconfig_gnmi_proto_target_target_proto_rawDescOnce sync.Once
-	file_github_com_openconfig_gnmi_proto_target_target_proto_rawDescData = file_github_com_openconfig_gnmi_proto_target_target_proto_rawDesc
+	file_github_com_openconfig_gnmi_proto_target_target_proto_rawDescData []byte
 )
 
 func file_github_com_openconfig_gnmi_proto_target_target_proto_rawDescGZIP() []byte {
 	file_github_com_openconfig_gnmi_proto_target_target_proto_rawDescOnce.Do(func() {
-		file_github_com_openconfig_gnmi_proto_target_target_proto_rawDescData = protoimpl.X.CompressGZIP(file_github_com_openconfig_gnmi_proto_target_target_proto_rawDescData)
+		file_github_com_openconfig_gnmi_proto_target_target_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_github_com_openconfig_gnmi_proto_target_target_proto_rawDesc), len(file_github_com_openconfig_gnmi_proto_target_target_proto_rawDesc)))
 	})
 	return file_github_com_openconfig_gnmi_proto_target_target_proto_rawDescData
 }
@@ -370,7 +368,7 @@ func file_github_com_openconfig_gnmi_proto_target_target_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_github_com_openconfig_gnmi_proto_target_target_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_github_com_openconfig_gnmi_proto_target_target_proto_rawDesc), len(file_github_com_openconfig_gnmi_proto_target_target_proto_rawDesc)),
 			NumEnums:      0,
 			NumMessages:   6,
 			NumExtensions: 0,
@@ -381,7 +379,6 @@ func file_github_com_openconfig_gnmi_proto_target_target_proto_init() {
 		MessageInfos:      file_github_com_openconfig_gnmi_proto_target_target_proto_msgTypes,
 	}.Build()
 	File_github_com_openconfig_gnmi_proto_target_target_proto = out.File
-	file_github_com_openconfig_gnmi_proto_target_target_proto_rawDesc = nil
 	file_github_com_openconfig_gnmi_proto_target_target_proto_goTypes = nil
 	file_github_com_openconfig_gnmi_proto_target_target_proto_depIdxs = nil
 }
diff --git a/api/go/github.com/openconfig/gnmi/testing/fake/proto/fake.pb.go b/api/go/github.com/openconfig/gnmi/testing/fake/proto/fake.pb.go
index 1beb87208..18fcb6386 100755
--- a/api/go/github.com/openconfig/gnmi/testing/fake/proto/fake.pb.go
+++ b/api/go/github.com/openconfig/gnmi/testing/fake/proto/fake.pb.go
@@ -4,7 +4,7 @@
 
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: github.com/openconfig/gnmi/testing/fake/proto/fake.proto
 
@@ -17,6 +17,7 @@ import (
 	anypb "google.golang.org/protobuf/types/known/anypb"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -130,12 +131,11 @@ func (Config_ClientType) EnumDescriptor() ([]byte, []int) {
 // Configuration is used to store all agent configuration for the fake agent
 // server.  Each config describes a single agent hosted on the server.
 type Configuration struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// Repeated list of targets to emulate.
-	Config []*Config `protobuf:"bytes,1,rep,name=config,proto3" json:"config,omitempty"`
+	Config        []*Config `protobuf:"bytes,1,rep,name=config,proto3" json:"config,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Configuration) Reset() {
@@ -176,12 +176,11 @@ func (x *Configuration) GetConfig() []*Config {
 }
 
 type Credentials struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Username      string                 `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"`
+	Password      string                 `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"`
-	Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Credentials) Reset() {
@@ -231,10 +230,7 @@ func (x *Credentials) GetPassword() string {
 // Config is a collection of values that together represent the update streams
 // for one or more fake devices.
 type Config struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// The target for which the fake will publish values for.
 	Target string `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"`
 	// Port for the agent to listen on. If 0 or unset the agent will pick a port
@@ -269,7 +265,7 @@ type Config struct {
 	EnableDelay bool `protobuf:"varint,10,opt,name=enable_delay,json=enableDelay,proto3" json:"enable_delay,omitempty"`
 	// Generator for value series for the target.
 	//
-	// Types that are assignable to Generator:
+	// Types that are valid to be assigned to Generator:
 	//
 	//	*Config_Custom
 	//	*Config_Random
@@ -278,7 +274,9 @@ type Config struct {
 	// tunnel_addr is the address of the tunnel server.
 	TunnelAddr string `protobuf:"bytes,11,opt,name=tunnel_addr,json=tunnelAddr,proto3" json:"tunnel_addr,omitempty"`
 	// tunnel_crt is the certificate file for the tunnel conection.
-	TunnelCrt string `protobuf:"bytes,12,opt,name=tunnel_crt,json=tunnelCrt,proto3" json:"tunnel_crt,omitempty"`
+	TunnelCrt     string `protobuf:"bytes,12,opt,name=tunnel_crt,json=tunnelCrt,proto3" json:"tunnel_crt,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Config) Reset() {
@@ -383,30 +381,36 @@ func (x *Config) GetEnableDelay() bool {
 	return false
 }
 
-func (m *Config) GetGenerator() isConfig_Generator {
-	if m != nil {
-		return m.Generator
+func (x *Config) GetGenerator() isConfig_Generator {
+	if x != nil {
+		return x.Generator
 	}
 	return nil
 }
 
 func (x *Config) GetCustom() *anypb.Any {
-	if x, ok := x.GetGenerator().(*Config_Custom); ok {
-		return x.Custom
+	if x != nil {
+		if x, ok := x.Generator.(*Config_Custom); ok {
+			return x.Custom
+		}
 	}
 	return nil
 }
 
 func (x *Config) GetRandom() *RandomGenerator {
-	if x, ok := x.GetGenerator().(*Config_Random); ok {
-		return x.Random
+	if x != nil {
+		if x, ok := x.Generator.(*Config_Random); ok {
+			return x.Random
+		}
 	}
 	return nil
 }
 
 func (x *Config) GetFixed() *FixedGenerator {
-	if x, ok := x.GetGenerator().(*Config_Fixed); ok {
-		return x.Fixed
+	if x != nil {
+		if x, ok := x.Generator.(*Config_Fixed); ok {
+			return x.Fixed
+		}
 	}
 	return nil
 }
@@ -448,11 +452,10 @@ func (*Config_Random) isConfig_Generator() {}
 func (*Config_Fixed) isConfig_Generator() {}
 
 type FixedGenerator struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState    `protogen:"open.v1"`
+	Responses     []*gnmi.SubscribeResponse `protobuf:"bytes,1,rep,name=responses,proto3" json:"responses,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Responses []*gnmi.SubscribeResponse `protobuf:"bytes,1,rep,name=responses,proto3" json:"responses,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *FixedGenerator) Reset() {
@@ -493,12 +496,11 @@ func (x *FixedGenerator) GetResponses() []*gnmi.SubscribeResponse {
 }
 
 type RandomGenerator struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Seed          int64                  `protobuf:"varint,1,opt,name=seed,proto3" json:"seed,omitempty"`
+	Values        []*Value               `protobuf:"bytes,2,rep,name=values,proto3" json:"values,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Seed   int64    `protobuf:"varint,1,opt,name=seed,proto3" json:"seed,omitempty"`
-	Values []*Value `protobuf:"bytes,2,rep,name=values,proto3" json:"values,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *RandomGenerator) Reset() {
@@ -547,9 +549,9 @@ func (x *RandomGenerator) GetValues() []*Value {
 
 // Delete will cause the value to be deleted at the Value's path.
 type DeleteValue struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
 	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeleteValue) Reset() {
@@ -586,10 +588,7 @@ func (*DeleteValue) Descriptor() ([]byte, []int) {
 // path.  A file containing a list of values can be used to simulate a network
 // device for integration tests.
 type Value struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// The device specific, or OpenConfig path corresponding to a value.
 	Path []string `protobuf:"bytes,1,rep,name=path,proto3" json:"path,omitempty"`
 	// The initial timestamp and configuration on how the timestamp will change
@@ -605,7 +604,7 @@ type Value struct {
 	// The initial value of the chosen type including configuration on how the
 	// value will mutate for subsequent updates.
 	//
-	// Types that are assignable to Value:
+	// Types that are valid to be assigned to Value:
 	//
 	//	*Value_IntValue
 	//	*Value_DoubleValue
@@ -615,7 +614,9 @@ type Value struct {
 	//	*Value_BoolValue
 	//	*Value_UintValue
 	//	*Value_StringListValue
-	Value isValue_Value `protobuf_oneof:"value"`
+	Value         isValue_Value `protobuf_oneof:"value"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Value) Reset() {
@@ -676,65 +677,81 @@ func (x *Value) GetSeed() int64 {
 	return 0
 }
 
-func (m *Value) GetValue() isValue_Value {
-	if m != nil {
-		return m.Value
+func (x *Value) GetValue() isValue_Value {
+	if x != nil {
+		return x.Value
 	}
 	return nil
 }
 
 func (x *Value) GetIntValue() *IntValue {
-	if x, ok := x.GetValue().(*Value_IntValue); ok {
-		return x.IntValue
+	if x != nil {
+		if x, ok := x.Value.(*Value_IntValue); ok {
+			return x.IntValue
+		}
 	}
 	return nil
 }
 
 func (x *Value) GetDoubleValue() *DoubleValue {
-	if x, ok := x.GetValue().(*Value_DoubleValue); ok {
-		return x.DoubleValue
+	if x != nil {
+		if x, ok := x.Value.(*Value_DoubleValue); ok {
+			return x.DoubleValue
+		}
 	}
 	return nil
 }
 
 func (x *Value) GetStringValue() *StringValue {
-	if x, ok := x.GetValue().(*Value_StringValue); ok {
-		return x.StringValue
+	if x != nil {
+		if x, ok := x.Value.(*Value_StringValue); ok {
+			return x.StringValue
+		}
 	}
 	return nil
 }
 
 func (x *Value) GetSync() uint64 {
-	if x, ok := x.GetValue().(*Value_Sync); ok {
-		return x.Sync
+	if x != nil {
+		if x, ok := x.Value.(*Value_Sync); ok {
+			return x.Sync
+		}
 	}
 	return 0
 }
 
 func (x *Value) GetDelete() *DeleteValue {
-	if x, ok := x.GetValue().(*Value_Delete); ok {
-		return x.Delete
+	if x != nil {
+		if x, ok := x.Value.(*Value_Delete); ok {
+			return x.Delete
+		}
 	}
 	return nil
 }
 
 func (x *Value) GetBoolValue() *BoolValue {
-	if x, ok := x.GetValue().(*Value_BoolValue); ok {
-		return x.BoolValue
+	if x != nil {
+		if x, ok := x.Value.(*Value_BoolValue); ok {
+			return x.BoolValue
+		}
 	}
 	return nil
 }
 
 func (x *Value) GetUintValue() *UintValue {
-	if x, ok := x.GetValue().(*Value_UintValue); ok {
-		return x.UintValue
+	if x != nil {
+		if x, ok := x.Value.(*Value_UintValue); ok {
+			return x.UintValue
+		}
 	}
 	return nil
 }
 
 func (x *Value) GetStringListValue() *StringListValue {
-	if x, ok := x.GetValue().(*Value_StringListValue); ok {
-		return x.StringListValue
+	if x != nil {
+		if x, ok := x.Value.(*Value_StringListValue); ok {
+			return x.StringListValue
+		}
 	}
 	return nil
 }
@@ -792,10 +809,7 @@ func (*Value_UintValue) isValue_Value() {}
 func (*Value_StringListValue) isValue_Value() {}
 
 type Timestamp struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// Initial timestamp for the corresponding value, nanoseconds since epoch.
 	// This value need have no relation to absolute real-time as the stream of
 	// of updates is generated without regard to the real clock and can be run
@@ -804,8 +818,10 @@ type Timestamp struct {
 	// These values will vary the change in the timestamp for subsequent outputs
 	// by a value between delta_min and delta_max.  Set to the same value to force
 	// a set periodic interval.
-	DeltaMin int64 `protobuf:"varint,2,opt,name=delta_min,json=deltaMin,proto3" json:"delta_min,omitempty"`
-	DeltaMax int64 `protobuf:"varint,3,opt,name=delta_max,json=deltaMax,proto3" json:"delta_max,omitempty"`
+	DeltaMin      int64 `protobuf:"varint,2,opt,name=delta_min,json=deltaMin,proto3" json:"delta_min,omitempty"`
+	DeltaMax      int64 `protobuf:"varint,3,opt,name=delta_max,json=deltaMax,proto3" json:"delta_max,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Timestamp) Reset() {
@@ -860,10 +876,7 @@ func (x *Timestamp) GetDeltaMax() int64 {
 }
 
 type IntValue struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// If distribution is IntRange, value is used as the initial value
 	// inside [minimum, maximum] and hold the value as it mutates.
 	// If distribution is IntList, value is only used to hold the value as it
@@ -871,11 +884,13 @@ type IntValue struct {
 	// If no distribution is set, value is used as it mutates, i.e. constant
 	// update.
 	Value int64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
-	// Types that are assignable to Distribution:
+	// Types that are valid to be assigned to Distribution:
 	//
 	//	*IntValue_Range
 	//	*IntValue_List
-	Distribution isIntValue_Distribution `protobuf_oneof:"distribution"`
+	Distribution  isIntValue_Distribution `protobuf_oneof:"distribution"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *IntValue) Reset() {
@@ -915,23 +930,27 @@ func (x *IntValue) GetValue() int64 {
 	return 0
 }
 
-func (m *IntValue) GetDistribution() isIntValue_Distribution {
-	if m != nil {
-		return m.Distribution
+func (x *IntValue) GetDistribution() isIntValue_Distribution {
+	if x != nil {
+		return x.Distribution
 	}
 	return nil
 }
 
 func (x *IntValue) GetRange() *IntRange {
-	if x, ok := x.GetDistribution().(*IntValue_Range); ok {
-		return x.Range
+	if x != nil {
+		if x, ok := x.Distribution.(*IntValue_Range); ok {
+			return x.Range
+		}
 	}
 	return nil
 }
 
 func (x *IntValue) GetList() *IntList {
-	if x, ok := x.GetDistribution().(*IntValue_List); ok {
-		return x.List
+	if x != nil {
+		if x, ok := x.Distribution.(*IntValue_List); ok {
+			return x.List
+		}
 	}
 	return nil
 }
@@ -953,10 +972,7 @@ func (*IntValue_Range) isIntValue_Distribution() {}
 func (*IntValue_List) isIntValue_Distribution() {}
 
 type IntRange struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// The range of the value allowed.
 	Minimum int64 `protobuf:"varint,1,opt,name=minimum,proto3" json:"minimum,omitempty"`
 	Maximum int64 `protobuf:"varint,2,opt,name=maximum,proto3" json:"maximum,omitempty"`
@@ -965,8 +981,10 @@ type IntRange struct {
 	// minimum and maximum are still respected and values will saturate at the
 	// boundaries if they are exceeded. If not set subsequent value is a value
 	// randomly chosen between minimum and maximum.
-	DeltaMin int64 `protobuf:"varint,3,opt,name=delta_min,json=deltaMin,proto3" json:"delta_min,omitempty"`
-	DeltaMax int64 `protobuf:"varint,4,opt,name=delta_max,json=deltaMax,proto3" json:"delta_max,omitempty"`
+	DeltaMin      int64 `protobuf:"varint,3,opt,name=delta_min,json=deltaMin,proto3" json:"delta_min,omitempty"`
+	DeltaMax      int64 `protobuf:"varint,4,opt,name=delta_max,json=deltaMax,proto3" json:"delta_max,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *IntRange) Reset() {
@@ -1028,15 +1046,14 @@ func (x *IntRange) GetDeltaMax() int64 {
 }
 
 type IntList struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// The set of values which can be used.
 	Options []int64 `protobuf:"varint,1,rep,packed,name=options,proto3" json:"options,omitempty"`
 	// Set to true to randomize selection of value from options. If false, the
 	// values are cycled in order, starting at index 0.
-	Random bool `protobuf:"varint,2,opt,name=random,proto3" json:"random,omitempty"`
+	Random        bool `protobuf:"varint,2,opt,name=random,proto3" json:"random,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *IntList) Reset() {
@@ -1084,10 +1101,7 @@ func (x *IntList) GetRandom() bool {
 }
 
 type DoubleValue struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// If distribution is DoubleRange, value is used as the initial value
 	// inside [minimum, maximum] and hold the value as it mutates.
 	// If distribution is DoubleList, value is only used to hold the value as it
@@ -1095,11 +1109,13 @@ type DoubleValue struct {
 	// If no distribution is set, value is used as it mutates, i.e. constant
 	// update.
 	Value float64 `protobuf:"fixed64,1,opt,name=value,proto3" json:"value,omitempty"`
-	// Types that are assignable to Distribution:
+	// Types that are valid to be assigned to Distribution:
 	//
 	//	*DoubleValue_Range
 	//	*DoubleValue_List
-	Distribution isDoubleValue_Distribution `protobuf_oneof:"distribution"`
+	Distribution  isDoubleValue_Distribution `protobuf_oneof:"distribution"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DoubleValue) Reset() {
@@ -1139,23 +1155,27 @@ func (x *DoubleValue) GetValue() float64 {
 	return 0
 }
 
-func (m *DoubleValue) GetDistribution() isDoubleValue_Distribution {
-	if m != nil {
-		return m.Distribution
+func (x *DoubleValue) GetDistribution() isDoubleValue_Distribution {
+	if x != nil {
+		return x.Distribution
 	}
 	return nil
 }
 
 func (x *DoubleValue) GetRange() *DoubleRange {
-	if x, ok := x.GetDistribution().(*DoubleValue_Range); ok {
-		return x.Range
+	if x != nil {
+		if x, ok := x.Distribution.(*DoubleValue_Range); ok {
+			return x.Range
+		}
 	}
 	return nil
 }
 
 func (x *DoubleValue) GetList() *DoubleList {
-	if x, ok := x.GetDistribution().(*DoubleValue_List); ok {
-		return x.List
+	if x != nil {
+		if x, ok := x.Distribution.(*DoubleValue_List); ok {
+			return x.List
+		}
 	}
 	return nil
 }
@@ -1177,10 +1197,7 @@ func (*DoubleValue_Range) isDoubleValue_Distribution() {}
 func (*DoubleValue_List) isDoubleValue_Distribution() {}
 
 type DoubleRange struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// The range of the value allowed.
 	Minimum float64 `protobuf:"fixed64,1,opt,name=minimum,proto3" json:"minimum,omitempty"`
 	Maximum float64 `protobuf:"fixed64,2,opt,name=maximum,proto3" json:"maximum,omitempty"`
@@ -1188,8 +1205,10 @@ type DoubleRange struct {
 	// where delta is randomly chosen between delta_min and delta_max. The range
 	// minimum and maximum are still respected. If not set subsequent value is a
 	// value randomly chosen between minimum and maximum.
-	DeltaMin float64 `protobuf:"fixed64,3,opt,name=delta_min,json=deltaMin,proto3" json:"delta_min,omitempty"`
-	DeltaMax float64 `protobuf:"fixed64,4,opt,name=delta_max,json=deltaMax,proto3" json:"delta_max,omitempty"`
+	DeltaMin      float64 `protobuf:"fixed64,3,opt,name=delta_min,json=deltaMin,proto3" json:"delta_min,omitempty"`
+	DeltaMax      float64 `protobuf:"fixed64,4,opt,name=delta_max,json=deltaMax,proto3" json:"delta_max,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DoubleRange) Reset() {
@@ -1251,15 +1270,14 @@ func (x *DoubleRange) GetDeltaMax() float64 {
 }
 
 type DoubleList struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// The set of values which can be used.
 	Options []float64 `protobuf:"fixed64,1,rep,packed,name=options,proto3" json:"options,omitempty"`
 	// Set to true to randomize selection of value from options. If false, the
 	// values are cycled in order.
-	Random bool `protobuf:"varint,2,opt,name=random,proto3" json:"random,omitempty"`
+	Random        bool `protobuf:"varint,2,opt,name=random,proto3" json:"random,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DoubleList) Reset() {
@@ -1307,19 +1325,18 @@ func (x *DoubleList) GetRandom() bool {
 }
 
 type StringValue struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// If distribution is StringList, value is used to hold the value as it
 	// mutates.
 	// If no distribution is set, value is used as it mutates, i.e. constant
 	// update.
 	Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
-	// Types that are assignable to Distribution:
+	// Types that are valid to be assigned to Distribution:
 	//
 	//	*StringValue_List
-	Distribution isStringValue_Distribution `protobuf_oneof:"distribution"`
+	Distribution  isStringValue_Distribution `protobuf_oneof:"distribution"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *StringValue) Reset() {
@@ -1359,16 +1376,18 @@ func (x *StringValue) GetValue() string {
 	return ""
 }
 
-func (m *StringValue) GetDistribution() isStringValue_Distribution {
-	if m != nil {
-		return m.Distribution
+func (x *StringValue) GetDistribution() isStringValue_Distribution {
+	if x != nil {
+		return x.Distribution
 	}
 	return nil
 }
 
 func (x *StringValue) GetList() *StringList {
-	if x, ok := x.GetDistribution().(*StringValue_List); ok {
-		return x.List
+	if x != nil {
+		if x, ok := x.Distribution.(*StringValue_List); ok {
+			return x.List
+		}
 	}
 	return nil
 }
@@ -1384,15 +1403,14 @@ type StringValue_List struct {
 func (*StringValue_List) isStringValue_Distribution() {}
 
 type StringList struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// The set of strings which can be used.
 	Options []string `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty"`
 	// Set to true to randomize selection of value from options. If false, the
 	// values are cycled in order, starting at index 0.
-	Random bool `protobuf:"varint,2,opt,name=random,proto3" json:"random,omitempty"`
+	Random        bool `protobuf:"varint,2,opt,name=random,proto3" json:"random,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *StringList) Reset() {
@@ -1440,19 +1458,18 @@ func (x *StringList) GetRandom() bool {
 }
 
 type StringListValue struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// If distribution is StringList, value is used to hold the value as it
 	// mutates.
 	// If no distribution is set, value is used as it mutates, i.e. constant
 	// update.
 	Value []string `protobuf:"bytes,1,rep,name=value,proto3" json:"value,omitempty"`
-	// Types that are assignable to Distribution:
+	// Types that are valid to be assigned to Distribution:
 	//
 	//	*StringListValue_List
-	Distribution isStringListValue_Distribution `protobuf_oneof:"distribution"`
+	Distribution  isStringListValue_Distribution `protobuf_oneof:"distribution"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *StringListValue) Reset() {
@@ -1492,16 +1509,18 @@ func (x *StringListValue) GetValue() []string {
 	return nil
 }
 
-func (m *StringListValue) GetDistribution() isStringListValue_Distribution {
-	if m != nil {
-		return m.Distribution
+func (x *StringListValue) GetDistribution() isStringListValue_Distribution {
+	if x != nil {
+		return x.Distribution
 	}
 	return nil
 }
 
 func (x *StringListValue) GetList() *StringList {
-	if x, ok := x.GetDistribution().(*StringListValue_List); ok {
-		return x.List
+	if x != nil {
+		if x, ok := x.Distribution.(*StringListValue_List); ok {
+			return x.List
+		}
 	}
 	return nil
 }
@@ -1517,19 +1536,18 @@ type StringListValue_List struct {
 func (*StringListValue_List) isStringListValue_Distribution() {}
 
 type BoolValue struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// If distribution is BoolList, value is only used to hold the value as it
 	// mutates.
 	// If no distribution is set, value is used as it mutates, i.e. constant
 	// update.
 	Value bool `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
-	// Types that are assignable to Distribution:
+	// Types that are valid to be assigned to Distribution:
 	//
 	//	*BoolValue_List
-	Distribution isBoolValue_Distribution `protobuf_oneof:"distribution"`
+	Distribution  isBoolValue_Distribution `protobuf_oneof:"distribution"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *BoolValue) Reset() {
@@ -1569,16 +1587,18 @@ func (x *BoolValue) GetValue() bool {
 	return false
 }
 
-func (m *BoolValue) GetDistribution() isBoolValue_Distribution {
-	if m != nil {
-		return m.Distribution
+func (x *BoolValue) GetDistribution() isBoolValue_Distribution {
+	if x != nil {
+		return x.Distribution
 	}
 	return nil
 }
 
 func (x *BoolValue) GetList() *BoolList {
-	if x, ok := x.GetDistribution().(*BoolValue_List); ok {
-		return x.List
+	if x != nil {
+		if x, ok := x.Distribution.(*BoolValue_List); ok {
+			return x.List
+		}
 	}
 	return nil
 }
@@ -1594,15 +1614,14 @@ type BoolValue_List struct {
 func (*BoolValue_List) isBoolValue_Distribution() {}
 
 type BoolList struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// The set of values which can be used.
 	Options []bool `protobuf:"varint,1,rep,packed,name=options,proto3" json:"options,omitempty"`
 	// Set to true to randomize selection of value from options. If false, the
 	// values are cycled in order, starting at index 0.
-	Random bool `protobuf:"varint,2,opt,name=random,proto3" json:"random,omitempty"`
+	Random        bool `protobuf:"varint,2,opt,name=random,proto3" json:"random,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *BoolList) Reset() {
@@ -1650,10 +1669,7 @@ func (x *BoolList) GetRandom() bool {
 }
 
 type UintValue struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// If distribution is UintRange, value is used as the initial value
 	// inside [minimum, maximum] and hold the value as it mutates.
 	// If distribution is UintList, value is only used to hold the value as it
@@ -1661,11 +1677,13 @@ type UintValue struct {
 	// If no distribution is set, value is used as it mutates, i.e. constant
 	// update.
 	Value uint64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
-	// Types that are assignable to Distribution:
+	// Types that are valid to be assigned to Distribution:
 	//
 	//	*UintValue_Range
 	//	*UintValue_List
-	Distribution isUintValue_Distribution `protobuf_oneof:"distribution"`
+	Distribution  isUintValue_Distribution `protobuf_oneof:"distribution"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *UintValue) Reset() {
@@ -1705,23 +1723,27 @@ func (x *UintValue) GetValue() uint64 {
 	return 0
 }
 
-func (m *UintValue) GetDistribution() isUintValue_Distribution {
-	if m != nil {
-		return m.Distribution
+func (x *UintValue) GetDistribution() isUintValue_Distribution {
+	if x != nil {
+		return x.Distribution
 	}
 	return nil
 }
 
 func (x *UintValue) GetRange() *UintRange {
-	if x, ok := x.GetDistribution().(*UintValue_Range); ok {
-		return x.Range
+	if x != nil {
+		if x, ok := x.Distribution.(*UintValue_Range); ok {
+			return x.Range
+		}
 	}
 	return nil
 }
 
 func (x *UintValue) GetList() *UintList {
-	if x, ok := x.GetDistribution().(*UintValue_List); ok {
-		return x.List
+	if x != nil {
+		if x, ok := x.Distribution.(*UintValue_List); ok {
+			return x.List
+		}
 	}
 	return nil
 }
@@ -1743,10 +1765,7 @@ func (*UintValue_Range) isUintValue_Distribution() {}
 func (*UintValue_List) isUintValue_Distribution() {}
 
 type UintRange struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// The range of the value allowed.
 	Minimum uint64 `protobuf:"varint,1,opt,name=minimum,proto3" json:"minimum,omitempty"`
 	Maximum uint64 `protobuf:"varint,2,opt,name=maximum,proto3" json:"maximum,omitempty"`
@@ -1755,8 +1774,10 @@ type UintRange struct {
 	// minimum and maximum are still respected and values will saturate at the
 	// boundaries if they are exceeded. If not set subsequent value is a value
 	// randomly chosen between minimum and maximum.
-	DeltaMin int64 `protobuf:"varint,3,opt,name=delta_min,json=deltaMin,proto3" json:"delta_min,omitempty"`
-	DeltaMax int64 `protobuf:"varint,4,opt,name=delta_max,json=deltaMax,proto3" json:"delta_max,omitempty"`
+	DeltaMin      int64 `protobuf:"varint,3,opt,name=delta_min,json=deltaMin,proto3" json:"delta_min,omitempty"`
+	DeltaMax      int64 `protobuf:"varint,4,opt,name=delta_max,json=deltaMax,proto3" json:"delta_max,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *UintRange) Reset() {
@@ -1818,15 +1839,14 @@ func (x *UintRange) GetDeltaMax() int64 {
 }
 
 type UintList struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state protoimpl.MessageState `protogen:"open.v1"`
 	// The set of values which can be used.
 	Options []uint64 `protobuf:"varint,1,rep,packed,name=options,proto3" json:"options,omitempty"`
 	// Set to true to randomize selection of value from options. If false, the
 	// values are cycled in order, starting at index 0.
-	Random bool `protobuf:"varint,2,opt,name=random,proto3" json:"random,omitempty"`
+	Random        bool `protobuf:"varint,2,opt,name=random,proto3" json:"random,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *UintList) Reset() {
@@ -1875,7 +1895,7 @@ func (x *UintList) GetRandom() bool {
 
 var File_github_com_openconfig_gnmi_testing_fake_proto_fake_proto protoreflect.FileDescriptor
 
-var file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_rawDesc = []byte{
+var file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_rawDesc = string([]byte{
 	0x0a, 0x38, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65,
 	0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x67, 0x6e, 0x6d, 0x69, 0x2f, 0x74, 0x65, 0x73,
 	0x74, 0x69, 0x6e, 0x67, 0x2f, 0x66, 0x61, 0x6b, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f,
@@ -2092,16 +2112,16 @@ var file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_rawDesc = []by
 	0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x67, 0x6e, 0x6d, 0x69, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69,
 	0x6e, 0x67, 0x2f, 0x66, 0x61, 0x6b, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x67, 0x6e,
 	0x6d, 0x69, 0x5f, 0x66, 0x61, 0x6b, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_rawDescOnce sync.Once
-	file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_rawDescData = file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_rawDesc
+	file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_rawDescData []byte
 )
 
 func file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_rawDescGZIP() []byte {
 	file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_rawDescOnce.Do(func() {
-		file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_rawDescData = protoimpl.X.CompressGZIP(file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_rawDescData)
+		file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_rawDesc), len(file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_rawDesc)))
 	})
 	return file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_rawDescData
 }
@@ -2221,7 +2241,7 @@ func file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_rawDesc), len(file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_rawDesc)),
 			NumEnums:      2,
 			NumMessages:   22,
 			NumExtensions: 0,
@@ -2233,7 +2253,6 @@ func file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_init() {
 		MessageInfos:      file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_msgTypes,
 	}.Build()
 	File_github_com_openconfig_gnmi_testing_fake_proto_fake_proto = out.File
-	file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_rawDesc = nil
 	file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_goTypes = nil
 	file_github_com_openconfig_gnmi_testing_fake_proto_fake_proto_depIdxs = nil
 }
diff --git a/api/go/gosdn/app/app.pb.go b/api/go/gosdn/app/app.pb.go
index 8064592bd..2f69f65da 100755
--- a/api/go/gosdn/app/app.pb.go
+++ b/api/go/gosdn/app/app.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: gosdn/app/app.proto
 
@@ -15,6 +15,7 @@ import (
 	_ "google.golang.org/protobuf/types/descriptorpb"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -25,13 +26,12 @@ const (
 )
 
 type AppRegisterRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Appname       string                 `protobuf:"bytes,2,opt,name=appname,proto3" json:"appname,omitempty"`
+	Token         string                 `protobuf:"bytes,3,opt,name=token,proto3" json:"token,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Appname   string `protobuf:"bytes,2,opt,name=appname,proto3" json:"appname,omitempty"`
-	Token     string `protobuf:"bytes,3,opt,name=token,proto3" json:"token,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *AppRegisterRequest) Reset() {
@@ -86,12 +86,11 @@ func (x *AppRegisterRequest) GetToken() string {
 }
 
 type AppRegisterResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Timestamp       int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Queueconnection string `protobuf:"bytes,2,opt,name=queueconnection,proto3" json:"queueconnection,omitempty"`
+	state           protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp       int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Queueconnection string                 `protobuf:"bytes,2,opt,name=queueconnection,proto3" json:"queueconnection,omitempty"`
+	unknownFields   protoimpl.UnknownFields
+	sizeCache       protoimpl.SizeCache
 }
 
 func (x *AppRegisterResponse) Reset() {
@@ -139,12 +138,11 @@ func (x *AppRegisterResponse) GetQueueconnection() string {
 }
 
 type AppDeregisterRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Appname       string                 `protobuf:"bytes,2,opt,name=appname,proto3" json:"appname,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Appname   string `protobuf:"bytes,2,opt,name=appname,proto3" json:"appname,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *AppDeregisterRequest) Reset() {
@@ -192,11 +190,10 @@ func (x *AppDeregisterRequest) GetAppname() string {
 }
 
 type AppDeregisterResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *AppDeregisterResponse) Reset() {
@@ -238,7 +235,7 @@ func (x *AppDeregisterResponse) GetTimestamp() int64 {
 
 var File_gosdn_app_app_proto protoreflect.FileDescriptor
 
-var file_gosdn_app_app_proto_rawDesc = []byte{
+var file_gosdn_app_app_proto_rawDesc = string([]byte{
 	0x0a, 0x13, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x61, 0x70, 0x70, 0x2e,
 	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x61, 0x70, 0x70,
 	0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e,
@@ -290,16 +287,16 @@ var file_gosdn_app_app_proto_rawDesc = []byte{
 	0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f,
 	0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70, 0x70, 0x62, 0x06, 0x70, 0x72,
 	0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_gosdn_app_app_proto_rawDescOnce sync.Once
-	file_gosdn_app_app_proto_rawDescData = file_gosdn_app_app_proto_rawDesc
+	file_gosdn_app_app_proto_rawDescData []byte
 )
 
 func file_gosdn_app_app_proto_rawDescGZIP() []byte {
 	file_gosdn_app_app_proto_rawDescOnce.Do(func() {
-		file_gosdn_app_app_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdn_app_app_proto_rawDescData)
+		file_gosdn_app_app_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gosdn_app_app_proto_rawDesc), len(file_gosdn_app_app_proto_rawDesc)))
 	})
 	return file_gosdn_app_app_proto_rawDescData
 }
@@ -332,7 +329,7 @@ func file_gosdn_app_app_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdn_app_app_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_gosdn_app_app_proto_rawDesc), len(file_gosdn_app_app_proto_rawDesc)),
 			NumEnums:      0,
 			NumMessages:   4,
 			NumExtensions: 0,
@@ -343,7 +340,6 @@ func file_gosdn_app_app_proto_init() {
 		MessageInfos:      file_gosdn_app_app_proto_msgTypes,
 	}.Build()
 	File_gosdn_app_app_proto = out.File
-	file_gosdn_app_app_proto_rawDesc = nil
 	file_gosdn_app_app_proto_goTypes = nil
 	file_gosdn_app_app_proto_depIdxs = nil
 }
diff --git a/api/go/gosdn/app/app.pb.gw.go b/api/go/gosdn/app/app.pb.gw.go
index 8ff05688f..852173e5a 100755
--- a/api/go/gosdn/app/app.pb.gw.go
+++ b/api/go/gosdn/app/app.pb.gw.go
@@ -10,6 +10,7 @@ package app
 
 import (
 	"context"
+	"errors"
 	"io"
 	"net/http"
 
@@ -24,63 +25,62 @@ import (
 )
 
 // Suppress "imported and not used" errors
-var _ codes.Code
-var _ io.Reader
-var _ status.Status
-var _ = runtime.String
-var _ = utilities.NewDoubleArray
-var _ = metadata.Join
+var (
+	_ codes.Code
+	_ io.Reader
+	_ status.Status
+	_ = errors.New
+	_ = runtime.String
+	_ = utilities.NewDoubleArray
+	_ = metadata.Join
+)
 
 func request_AppService_Register_0(ctx context.Context, marshaler runtime.Marshaler, client AppServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq AppRegisterRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq AppRegisterRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.Register(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_AppService_Register_0(ctx context.Context, marshaler runtime.Marshaler, server AppServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq AppRegisterRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq AppRegisterRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.Register(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 func request_AppService_Deregister_0(ctx context.Context, marshaler runtime.Marshaler, client AppServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq AppDeregisterRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq AppDeregisterRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.Deregister(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_AppService_Deregister_0(ctx context.Context, marshaler runtime.Marshaler, server AppServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq AppDeregisterRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq AppDeregisterRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.Deregister(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 // RegisterAppServiceHandlerServer registers the http handlers for service AppService to "mux".
@@ -89,16 +89,13 @@ func local_request_AppService_Deregister_0(ctx context.Context, marshaler runtim
 // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterAppServiceHandlerFromEndpoint instead.
 // GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
 func RegisterAppServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server AppServiceServer) error {
-
-	mux.Handle("POST", pattern_AppService_Register_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_AppService_Register_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.app.AppService/Register", runtime.WithHTTPPathPattern("/register"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.app.AppService/Register", runtime.WithHTTPPathPattern("/register"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -110,20 +107,15 @@ func RegisterAppServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux,
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_AppService_Register_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_AppService_Deregister_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_AppService_Deregister_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.app.AppService/Deregister", runtime.WithHTTPPathPattern("/deregister"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.app.AppService/Deregister", runtime.WithHTTPPathPattern("/deregister"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -135,9 +127,7 @@ func RegisterAppServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux,
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_AppService_Deregister_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
 
 	return nil
@@ -164,7 +154,6 @@ func RegisterAppServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.Ser
 			}
 		}()
 	}()
-
 	return RegisterAppServiceHandler(ctx, mux, conn)
 }
 
@@ -180,14 +169,11 @@ func RegisterAppServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn
 // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
 // "AppServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares.
 func RegisterAppServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client AppServiceClient) error {
-
-	mux.Handle("POST", pattern_AppService_Register_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_AppService_Register_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.app.AppService/Register", runtime.WithHTTPPathPattern("/register"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.app.AppService/Register", runtime.WithHTTPPathPattern("/register"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -198,18 +184,13 @@ func RegisterAppServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux,
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_AppService_Register_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_AppService_Deregister_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_AppService_Deregister_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.app.AppService/Deregister", runtime.WithHTTPPathPattern("/deregister"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.app.AppService/Deregister", runtime.WithHTTPPathPattern("/deregister"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -220,22 +201,17 @@ func RegisterAppServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux,
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_AppService_Deregister_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
 	return nil
 }
 
 var (
-	pattern_AppService_Register_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"register"}, ""))
-
+	pattern_AppService_Register_0   = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"register"}, ""))
 	pattern_AppService_Deregister_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"deregister"}, ""))
 )
 
 var (
-	forward_AppService_Register_0 = runtime.ForwardResponseMessage
-
+	forward_AppService_Register_0   = runtime.ForwardResponseMessage
 	forward_AppService_Deregister_0 = runtime.ForwardResponseMessage
 )
diff --git a/api/go/gosdn/configurationmanagement/configurationmanagement.pb.go b/api/go/gosdn/configurationmanagement/configurationmanagement.pb.go
index b4600ce3f..1a8b68cab 100755
--- a/api/go/gosdn/configurationmanagement/configurationmanagement.pb.go
+++ b/api/go/gosdn/configurationmanagement/configurationmanagement.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: gosdn/configurationmanagement/configurationmanagement.proto
 
@@ -14,6 +14,7 @@ import (
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -24,12 +25,11 @@ const (
 )
 
 type ExportSDNConfigRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Pid           string                 `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Pid       string `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *ExportSDNConfigRequest) Reset() {
@@ -77,12 +77,11 @@ func (x *ExportSDNConfigRequest) GetPid() string {
 }
 
 type ExportSDNConfigResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	SdnConfigData string                 `protobuf:"bytes,2,opt,name=sdnConfigData,proto3" json:"sdnConfigData,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp     int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	SdnConfigData string `protobuf:"bytes,2,opt,name=sdnConfigData,proto3" json:"sdnConfigData,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *ExportSDNConfigResponse) Reset() {
@@ -130,13 +129,12 @@ func (x *ExportSDNConfigResponse) GetSdnConfigData() string {
 }
 
 type ImportSDNConfigRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Pid           string                 `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
+	SdnConfigData string                 `protobuf:"bytes,3,opt,name=sdnConfigData,proto3" json:"sdnConfigData,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp     int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Pid           string `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
-	SdnConfigData string `protobuf:"bytes,3,opt,name=sdnConfigData,proto3" json:"sdnConfigData,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *ImportSDNConfigRequest) Reset() {
@@ -191,11 +189,10 @@ func (x *ImportSDNConfigRequest) GetSdnConfigData() string {
 }
 
 type ImportSDNConfigResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *ImportSDNConfigResponse) Reset() {
@@ -237,7 +234,7 @@ func (x *ImportSDNConfigResponse) GetTimestamp() int64 {
 
 var File_gosdn_configurationmanagement_configurationmanagement_proto protoreflect.FileDescriptor
 
-var file_gosdn_configurationmanagement_configurationmanagement_proto_rawDesc = []byte{
+var file_gosdn_configurationmanagement_configurationmanagement_proto_rawDesc = string([]byte{
 	0x0a, 0x3b, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72,
 	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2f,
 	0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x61, 0x6e,
@@ -297,16 +294,16 @@ var file_gosdn_configurationmanagement_configurationmanagement_proto_rawDesc = [
 	0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70,
 	0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x62,
 	0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_gosdn_configurationmanagement_configurationmanagement_proto_rawDescOnce sync.Once
-	file_gosdn_configurationmanagement_configurationmanagement_proto_rawDescData = file_gosdn_configurationmanagement_configurationmanagement_proto_rawDesc
+	file_gosdn_configurationmanagement_configurationmanagement_proto_rawDescData []byte
 )
 
 func file_gosdn_configurationmanagement_configurationmanagement_proto_rawDescGZIP() []byte {
 	file_gosdn_configurationmanagement_configurationmanagement_proto_rawDescOnce.Do(func() {
-		file_gosdn_configurationmanagement_configurationmanagement_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdn_configurationmanagement_configurationmanagement_proto_rawDescData)
+		file_gosdn_configurationmanagement_configurationmanagement_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gosdn_configurationmanagement_configurationmanagement_proto_rawDesc), len(file_gosdn_configurationmanagement_configurationmanagement_proto_rawDesc)))
 	})
 	return file_gosdn_configurationmanagement_configurationmanagement_proto_rawDescData
 }
@@ -339,7 +336,7 @@ func file_gosdn_configurationmanagement_configurationmanagement_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdn_configurationmanagement_configurationmanagement_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_gosdn_configurationmanagement_configurationmanagement_proto_rawDesc), len(file_gosdn_configurationmanagement_configurationmanagement_proto_rawDesc)),
 			NumEnums:      0,
 			NumMessages:   4,
 			NumExtensions: 0,
@@ -350,7 +347,6 @@ func file_gosdn_configurationmanagement_configurationmanagement_proto_init() {
 		MessageInfos:      file_gosdn_configurationmanagement_configurationmanagement_proto_msgTypes,
 	}.Build()
 	File_gosdn_configurationmanagement_configurationmanagement_proto = out.File
-	file_gosdn_configurationmanagement_configurationmanagement_proto_rawDesc = nil
 	file_gosdn_configurationmanagement_configurationmanagement_proto_goTypes = nil
 	file_gosdn_configurationmanagement_configurationmanagement_proto_depIdxs = nil
 }
diff --git a/api/go/gosdn/configurationmanagement/configurationmanagement.pb.gw.go b/api/go/gosdn/configurationmanagement/configurationmanagement.pb.gw.go
index a0a3160e0..20532a162 100755
--- a/api/go/gosdn/configurationmanagement/configurationmanagement.pb.gw.go
+++ b/api/go/gosdn/configurationmanagement/configurationmanagement.pb.gw.go
@@ -10,6 +10,7 @@ package core
 
 import (
 	"context"
+	"errors"
 	"io"
 	"net/http"
 
@@ -24,151 +25,114 @@ import (
 )
 
 // Suppress "imported and not used" errors
-var _ codes.Code
-var _ io.Reader
-var _ status.Status
-var _ = runtime.String
-var _ = utilities.NewDoubleArray
-var _ = metadata.Join
-
 var (
-	filter_ConfigurationManagementService_ExportSDNConfig_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
+	_ codes.Code
+	_ io.Reader
+	_ status.Status
+	_ = errors.New
+	_ = runtime.String
+	_ = utilities.NewDoubleArray
+	_ = metadata.Join
 )
 
-func request_ConfigurationManagementService_ExportSDNConfig_0(ctx context.Context, marshaler runtime.Marshaler, client ConfigurationManagementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq ExportSDNConfigRequest
-	var metadata runtime.ServerMetadata
+var filter_ConfigurationManagementService_ExportSDNConfig_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
 
+func request_ConfigurationManagementService_ExportSDNConfig_0(ctx context.Context, marshaler runtime.Marshaler, client ConfigurationManagementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq ExportSDNConfigRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["pid"]
+	val, ok := pathParams["pid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "pid")
 	}
-
 	protoReq.Pid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "pid", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ConfigurationManagementService_ExportSDNConfig_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.ExportSDNConfig(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_ConfigurationManagementService_ExportSDNConfig_0(ctx context.Context, marshaler runtime.Marshaler, server ConfigurationManagementServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq ExportSDNConfigRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq ExportSDNConfigRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["pid"]
+	val, ok := pathParams["pid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "pid")
 	}
-
 	protoReq.Pid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "pid", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ConfigurationManagementService_ExportSDNConfig_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.ExportSDNConfig(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_ConfigurationManagementService_ImportSDNConfig_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
-)
+var filter_ConfigurationManagementService_ImportSDNConfig_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
 
 func request_ConfigurationManagementService_ImportSDNConfig_0(ctx context.Context, marshaler runtime.Marshaler, client ConfigurationManagementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq ImportSDNConfigRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq ImportSDNConfigRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["pid"]
+	val, ok := pathParams["pid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "pid")
 	}
-
 	protoReq.Pid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "pid", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ConfigurationManagementService_ImportSDNConfig_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.ImportSDNConfig(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_ConfigurationManagementService_ImportSDNConfig_0(ctx context.Context, marshaler runtime.Marshaler, server ConfigurationManagementServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq ImportSDNConfigRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq ImportSDNConfigRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["pid"]
+	val, ok := pathParams["pid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "pid")
 	}
-
 	protoReq.Pid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "pid", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ConfigurationManagementService_ImportSDNConfig_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.ImportSDNConfig(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 // RegisterConfigurationManagementServiceHandlerServer registers the http handlers for service ConfigurationManagementService to "mux".
@@ -177,16 +141,13 @@ func local_request_ConfigurationManagementService_ImportSDNConfig_0(ctx context.
 // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterConfigurationManagementServiceHandlerFromEndpoint instead.
 // GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
 func RegisterConfigurationManagementServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server ConfigurationManagementServiceServer) error {
-
-	mux.Handle("GET", pattern_ConfigurationManagementService_ExportSDNConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_ConfigurationManagementService_ExportSDNConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.configurationmanagement.ConfigurationManagementService/ExportSDNConfig", runtime.WithHTTPPathPattern("/export/{pid}"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.configurationmanagement.ConfigurationManagementService/ExportSDNConfig", runtime.WithHTTPPathPattern("/export/{pid}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -198,20 +159,15 @@ func RegisterConfigurationManagementServiceHandlerServer(ctx context.Context, mu
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_ConfigurationManagementService_ExportSDNConfig_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_ConfigurationManagementService_ImportSDNConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_ConfigurationManagementService_ImportSDNConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.configurationmanagement.ConfigurationManagementService/ImportSDNConfig", runtime.WithHTTPPathPattern("/import/{pid}"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.configurationmanagement.ConfigurationManagementService/ImportSDNConfig", runtime.WithHTTPPathPattern("/import/{pid}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -223,9 +179,7 @@ func RegisterConfigurationManagementServiceHandlerServer(ctx context.Context, mu
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_ConfigurationManagementService_ImportSDNConfig_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
 
 	return nil
@@ -252,7 +206,6 @@ func RegisterConfigurationManagementServiceHandlerFromEndpoint(ctx context.Conte
 			}
 		}()
 	}()
-
 	return RegisterConfigurationManagementServiceHandler(ctx, mux, conn)
 }
 
@@ -268,14 +221,11 @@ func RegisterConfigurationManagementServiceHandler(ctx context.Context, mux *run
 // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
 // "ConfigurationManagementServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares.
 func RegisterConfigurationManagementServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client ConfigurationManagementServiceClient) error {
-
-	mux.Handle("GET", pattern_ConfigurationManagementService_ExportSDNConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_ConfigurationManagementService_ExportSDNConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.configurationmanagement.ConfigurationManagementService/ExportSDNConfig", runtime.WithHTTPPathPattern("/export/{pid}"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.configurationmanagement.ConfigurationManagementService/ExportSDNConfig", runtime.WithHTTPPathPattern("/export/{pid}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -286,18 +236,13 @@ func RegisterConfigurationManagementServiceHandlerClient(ctx context.Context, mu
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_ConfigurationManagementService_ExportSDNConfig_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_ConfigurationManagementService_ImportSDNConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_ConfigurationManagementService_ImportSDNConfig_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.configurationmanagement.ConfigurationManagementService/ImportSDNConfig", runtime.WithHTTPPathPattern("/import/{pid}"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.configurationmanagement.ConfigurationManagementService/ImportSDNConfig", runtime.WithHTTPPathPattern("/import/{pid}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -308,22 +253,17 @@ func RegisterConfigurationManagementServiceHandlerClient(ctx context.Context, mu
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_ConfigurationManagementService_ImportSDNConfig_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
 	return nil
 }
 
 var (
 	pattern_ConfigurationManagementService_ExportSDNConfig_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"export", "pid"}, ""))
-
 	pattern_ConfigurationManagementService_ImportSDNConfig_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"import", "pid"}, ""))
 )
 
 var (
 	forward_ConfigurationManagementService_ExportSDNConfig_0 = runtime.ForwardResponseMessage
-
 	forward_ConfigurationManagementService_ImportSDNConfig_0 = runtime.ForwardResponseMessage
 )
diff --git a/api/go/gosdn/conflict/conflict.pb.go b/api/go/gosdn/conflict/conflict.pb.go
index a1c9d5c44..89b844920 100755
--- a/api/go/gosdn/conflict/conflict.pb.go
+++ b/api/go/gosdn/conflict/conflict.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: gosdn/conflict/conflict.proto
 
@@ -12,6 +12,7 @@ import (
 	_ "google.golang.org/protobuf/types/descriptorpb"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -22,11 +23,10 @@ const (
 )
 
 type Metadata struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	ResourceVersion int64 `protobuf:"varint,1,opt,name=resourceVersion,proto3" json:"resourceVersion,omitempty"`
+	state           protoimpl.MessageState `protogen:"open.v1"`
+	ResourceVersion int64                  `protobuf:"varint,1,opt,name=resourceVersion,proto3" json:"resourceVersion,omitempty"`
+	unknownFields   protoimpl.UnknownFields
+	sizeCache       protoimpl.SizeCache
 }
 
 func (x *Metadata) Reset() {
@@ -68,7 +68,7 @@ func (x *Metadata) GetResourceVersion() int64 {
 
 var File_gosdn_conflict_conflict_proto protoreflect.FileDescriptor
 
-var file_gosdn_conflict_conflict_proto_rawDesc = []byte{
+var file_gosdn_conflict_conflict_proto_rawDesc = string([]byte{
 	0x0a, 0x1d, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74,
 	0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
 	0x0e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x1a,
@@ -82,16 +82,16 @@ var file_gosdn_conflict_conflict_proto_rawDesc = []byte{
 	0x74, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67,
 	0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x62, 0x06, 0x70,
 	0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_gosdn_conflict_conflict_proto_rawDescOnce sync.Once
-	file_gosdn_conflict_conflict_proto_rawDescData = file_gosdn_conflict_conflict_proto_rawDesc
+	file_gosdn_conflict_conflict_proto_rawDescData []byte
 )
 
 func file_gosdn_conflict_conflict_proto_rawDescGZIP() []byte {
 	file_gosdn_conflict_conflict_proto_rawDescOnce.Do(func() {
-		file_gosdn_conflict_conflict_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdn_conflict_conflict_proto_rawDescData)
+		file_gosdn_conflict_conflict_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gosdn_conflict_conflict_proto_rawDesc), len(file_gosdn_conflict_conflict_proto_rawDesc)))
 	})
 	return file_gosdn_conflict_conflict_proto_rawDescData
 }
@@ -117,7 +117,7 @@ func file_gosdn_conflict_conflict_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdn_conflict_conflict_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_gosdn_conflict_conflict_proto_rawDesc), len(file_gosdn_conflict_conflict_proto_rawDesc)),
 			NumEnums:      0,
 			NumMessages:   1,
 			NumExtensions: 0,
@@ -128,7 +128,6 @@ func file_gosdn_conflict_conflict_proto_init() {
 		MessageInfos:      file_gosdn_conflict_conflict_proto_msgTypes,
 	}.Build()
 	File_gosdn_conflict_conflict_proto = out.File
-	file_gosdn_conflict_conflict_proto_rawDesc = nil
 	file_gosdn_conflict_conflict_proto_goTypes = nil
 	file_gosdn_conflict_conflict_proto_depIdxs = nil
 }
diff --git a/api/go/gosdn/csbi/csbi.pb.go b/api/go/gosdn/csbi/csbi.pb.go
index 55f5c6d63..39d930645 100755
--- a/api/go/gosdn/csbi/csbi.pb.go
+++ b/api/go/gosdn/csbi/csbi.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: gosdn/csbi/csbi.proto
 
@@ -13,6 +13,7 @@ import (
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -81,13 +82,12 @@ func (State) EnumDescriptor() ([]byte, []int) {
 }
 
 type Syn struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Id            string                 `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
+	Address       string                 `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Id        string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
-	Address   string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Syn) Reset() {
@@ -142,12 +142,11 @@ func (x *Syn) GetAddress() string {
 }
 
 type Ack struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state           protoimpl.MessageState     `protogen:"open.v1"`
 	Timestamp       int64                      `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
 	TransportOption *transport.TransportOption `protobuf:"bytes,2,opt,name=transport_option,json=transportOption,proto3" json:"transport_option,omitempty"`
+	unknownFields   protoimpl.UnknownFields
+	sizeCache       protoimpl.SizeCache
 }
 
 func (x *Ack) Reset() {
@@ -195,13 +194,12 @@ func (x *Ack) GetTransportOption() *transport.TransportOption {
 }
 
 type GetRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	All           bool                   `protobuf:"varint,2,opt,name=all,proto3" json:"all,omitempty"`
+	Did           []string               `protobuf:"bytes,3,rep,name=did,proto3" json:"did,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64    `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	All       bool     `protobuf:"varint,2,opt,name=all,proto3" json:"all,omitempty"`
-	Did       []string `protobuf:"bytes,3,rep,name=did,proto3" json:"did,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetRequest) Reset() {
@@ -256,13 +254,12 @@ func (x *GetRequest) GetDid() []string {
 }
 
 type GetPayloadRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Did           string                 `protobuf:"bytes,2,opt,name=did,proto3" json:"did,omitempty"`
+	File          string                 `protobuf:"bytes,3,opt,name=file,proto3" json:"file,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Did       string `protobuf:"bytes,2,opt,name=did,proto3" json:"did,omitempty"`
-	File      string `protobuf:"bytes,3,opt,name=file,proto3" json:"file,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetPayloadRequest) Reset() {
@@ -317,12 +314,11 @@ func (x *GetPayloadRequest) GetFile() string {
 }
 
 type GetResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Deployments   []*Deployment          `protobuf:"bytes,2,rep,name=deployments,proto3" json:"deployments,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp   int64         `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Deployments []*Deployment `protobuf:"bytes,2,rep,name=deployments,proto3" json:"deployments,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetResponse) Reset() {
@@ -370,13 +366,12 @@ func (x *GetResponse) GetDeployments() []*Deployment {
 }
 
 type Deployment struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Id            string                 `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	Name          string                 `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+	State         State                  `protobuf:"varint,3,opt,name=state,proto3,enum=gosdn.csbi.State" json:"state,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Id    string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	Name  string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
-	State State  `protobuf:"varint,3,opt,name=state,proto3,enum=gosdn.csbi.State" json:"state,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Deployment) Reset() {
@@ -431,12 +426,11 @@ func (x *Deployment) GetState() State {
 }
 
 type CreateRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state           protoimpl.MessageState       `protogen:"open.v1"`
 	Timestamp       int64                        `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
 	TransportOption []*transport.TransportOption `protobuf:"bytes,2,rep,name=transport_option,json=transportOption,proto3" json:"transport_option,omitempty"`
+	unknownFields   protoimpl.UnknownFields
+	sizeCache       protoimpl.SizeCache
 }
 
 func (x *CreateRequest) Reset() {
@@ -484,12 +478,11 @@ func (x *CreateRequest) GetTransportOption() []*transport.TransportOption {
 }
 
 type CreateResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Deployments   []*Deployment          `protobuf:"bytes,2,rep,name=deployments,proto3" json:"deployments,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp   int64         `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Deployments []*Deployment `protobuf:"bytes,2,rep,name=deployments,proto3" json:"deployments,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *CreateResponse) Reset() {
@@ -537,11 +530,10 @@ func (x *CreateResponse) GetDeployments() []*Deployment {
 }
 
 type Payload struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Chunk         []byte                 `protobuf:"bytes,1,opt,name=chunk,proto3" json:"chunk,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Chunk []byte `protobuf:"bytes,1,opt,name=chunk,proto3" json:"chunk,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Payload) Reset() {
@@ -582,12 +574,11 @@ func (x *Payload) GetChunk() []byte {
 }
 
 type DeleteRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Did           []string               `protobuf:"bytes,2,rep,name=did,proto3" json:"did,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64    `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Did       []string `protobuf:"bytes,2,rep,name=did,proto3" json:"did,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeleteRequest) Reset() {
@@ -635,11 +626,10 @@ func (x *DeleteRequest) GetDid() []string {
 }
 
 type DeleteResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeleteResponse) Reset() {
@@ -681,7 +671,7 @@ func (x *DeleteResponse) GetTimestamp() int64 {
 
 var File_gosdn_csbi_csbi_proto protoreflect.FileDescriptor
 
-var file_gosdn_csbi_csbi_proto_rawDesc = []byte{
+var file_gosdn_csbi_csbi_proto_rawDesc = string([]byte{
 	0x0a, 0x15, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x63, 0x73, 0x62, 0x69, 0x2f, 0x63, 0x73, 0x62,
 	0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x63,
 	0x73, 0x62, 0x69, 0x1a, 0x1b, 0x62, 0x75, 0x66, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74,
@@ -786,16 +776,16 @@ var file_gosdn_csbi_csbi_proto_rawDesc = []byte{
 	0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70,
 	0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x63, 0x73, 0x62, 0x69, 0x62,
 	0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_gosdn_csbi_csbi_proto_rawDescOnce sync.Once
-	file_gosdn_csbi_csbi_proto_rawDescData = file_gosdn_csbi_csbi_proto_rawDesc
+	file_gosdn_csbi_csbi_proto_rawDescData []byte
 )
 
 func file_gosdn_csbi_csbi_proto_rawDescGZIP() []byte {
 	file_gosdn_csbi_csbi_proto_rawDescOnce.Do(func() {
-		file_gosdn_csbi_csbi_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdn_csbi_csbi_proto_rawDescData)
+		file_gosdn_csbi_csbi_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gosdn_csbi_csbi_proto_rawDesc), len(file_gosdn_csbi_csbi_proto_rawDesc)))
 	})
 	return file_gosdn_csbi_csbi_proto_rawDescData
 }
@@ -851,7 +841,7 @@ func file_gosdn_csbi_csbi_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdn_csbi_csbi_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_gosdn_csbi_csbi_proto_rawDesc), len(file_gosdn_csbi_csbi_proto_rawDesc)),
 			NumEnums:      1,
 			NumMessages:   11,
 			NumExtensions: 0,
@@ -863,7 +853,6 @@ func file_gosdn_csbi_csbi_proto_init() {
 		MessageInfos:      file_gosdn_csbi_csbi_proto_msgTypes,
 	}.Build()
 	File_gosdn_csbi_csbi_proto = out.File
-	file_gosdn_csbi_csbi_proto_rawDesc = nil
 	file_gosdn_csbi_csbi_proto_goTypes = nil
 	file_gosdn_csbi_csbi_proto_depIdxs = nil
 }
diff --git a/api/go/gosdn/networkelement/networkelement.pb.go b/api/go/gosdn/networkelement/networkelement.pb.go
index a58431fdb..17e66647e 100755
--- a/api/go/gosdn/networkelement/networkelement.pb.go
+++ b/api/go/gosdn/networkelement/networkelement.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: gosdn/networkelement/networkelement.proto
 
@@ -19,6 +19,7 @@ import (
 	_ "google.golang.org/protobuf/types/descriptorpb"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -293,12 +294,11 @@ func (StreamMode) EnumDescriptor() ([]byte, []int) {
 
 // TODO: change name to fit the rest
 type UpdateNetworkElementRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state          protoimpl.MessageState `protogen:"open.v1"`
 	Timestamp      int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	NetworkElement *ManagedNetworkElement `protobuf:"bytes,2,opt,name=network_element,json=networkElement,proto3" json:"network_element,omitempty"`
+	unknownFields  protoimpl.UnknownFields
+	sizeCache      protoimpl.SizeCache
 }
 
 func (x *UpdateNetworkElementRequest) Reset() {
@@ -346,11 +346,10 @@ func (x *UpdateNetworkElementRequest) GetNetworkElement() *ManagedNetworkElement
 }
 
 type UpdateNetworkElementResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *UpdateNetworkElementResponse) Reset() {
@@ -391,10 +390,7 @@ func (x *UpdateNetworkElementResponse) GetTimestamp() int64 {
 }
 
 type ManagedNetworkElement struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state              protoimpl.MessageState     `protogen:"open.v1"`
 	Id                 string                     `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
 	Name               string                     `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
 	Model              string                     `protobuf:"bytes,3,opt,name=model,proto3" json:"model,omitempty"`
@@ -405,6 +401,8 @@ type ManagedNetworkElement struct {
 	Metadata           *conflict.Metadata         `protobuf:"bytes,8,opt,name=metadata,proto3" json:"metadata,omitempty"`
 	AssociatedPnd      string                     `protobuf:"bytes,9,opt,name=associated_pnd,json=associatedPnd,proto3" json:"associated_pnd,omitempty"`
 	GnmiSubscribePaths []string                   `protobuf:"bytes,10,rep,name=gnmi_subscribe_paths,json=gnmiSubscribePaths,proto3" json:"gnmi_subscribe_paths,omitempty"`
+	unknownFields      protoimpl.UnknownFields
+	sizeCache          protoimpl.SizeCache
 }
 
 func (x *ManagedNetworkElement) Reset() {
@@ -508,14 +506,13 @@ func (x *ManagedNetworkElement) GetGnmiSubscribePaths() []string {
 }
 
 type FlattenedManagedNetworkElement struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Id            string                 `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	Name          string                 `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+	Pid           string                 `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"`
+	Pluginid      string                 `protobuf:"bytes,4,opt,name=pluginid,proto3" json:"pluginid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Id       string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	Name     string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
-	Pid      string `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"`
-	Pluginid string `protobuf:"bytes,4,opt,name=pluginid,proto3" json:"pluginid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *FlattenedManagedNetworkElement) Reset() {
@@ -577,12 +574,11 @@ func (x *FlattenedManagedNetworkElement) GetPluginid() string {
 }
 
 type GetAllRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Pid           string                 `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Pid       string `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetAllRequest) Reset() {
@@ -630,15 +626,14 @@ func (x *GetAllRequest) GetPid() string {
 }
 
 type GetAllResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	state     protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
 	// TODO: Check if this is really needed. Perhaps a reference to the PND's ID
 	// is also sufficient.
-	Pnd *pnd.PrincipalNetworkDomain `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"`
-	Mne []*ManagedNetworkElement    `protobuf:"bytes,3,rep,name=mne,proto3" json:"mne,omitempty"`
+	Pnd           *pnd.PrincipalNetworkDomain `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"`
+	Mne           []*ManagedNetworkElement    `protobuf:"bytes,3,rep,name=mne,proto3" json:"mne,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetAllResponse) Reset() {
@@ -693,12 +688,11 @@ func (x *GetAllResponse) GetMne() []*ManagedNetworkElement {
 }
 
 type GetAllFlattenedRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Pid           string                 `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Pid       string `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetAllFlattenedRequest) Reset() {
@@ -746,15 +740,14 @@ func (x *GetAllFlattenedRequest) GetPid() string {
 }
 
 type GetAllFlattenedResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	state     protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
 	// TODO: Check if this is really needed. Perhaps a reference to the PND's ID
 	// is also sufficient.
-	Pnd *pnd.PrincipalNetworkDomain       `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"`
-	Mne []*FlattenedManagedNetworkElement `protobuf:"bytes,3,rep,name=mne,proto3" json:"mne,omitempty"`
+	Pnd           *pnd.PrincipalNetworkDomain       `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"`
+	Mne           []*FlattenedManagedNetworkElement `protobuf:"bytes,3,rep,name=mne,proto3" json:"mne,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetAllFlattenedResponse) Reset() {
@@ -809,12 +802,11 @@ func (x *GetAllFlattenedResponse) GetMne() []*FlattenedManagedNetworkElement {
 }
 
 type ParseYangRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Yang          string                 `protobuf:"bytes,2,opt,name=yang,proto3" json:"yang,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Yang      string `protobuf:"bytes,2,opt,name=yang,proto3" json:"yang,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *ParseYangRequest) Reset() {
@@ -862,12 +854,11 @@ func (x *ParseYangRequest) GetYang() string {
 }
 
 type ParseYangResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Json          string                 `protobuf:"bytes,2,opt,name=json,proto3" json:"json,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Json      string `protobuf:"bytes,2,opt,name=json,proto3" json:"json,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *ParseYangResponse) Reset() {
@@ -915,13 +906,12 @@ func (x *ParseYangResponse) GetJson() string {
 }
 
 type GetRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Mneid         string                 `protobuf:"bytes,2,opt,name=mneid,proto3" json:"mneid,omitempty"`
+	Pid           string                 `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Mneid     string `protobuf:"bytes,2,opt,name=mneid,proto3" json:"mneid,omitempty"`
-	Pid       string `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetRequest) Reset() {
@@ -976,15 +966,14 @@ func (x *GetRequest) GetPid() string {
 }
 
 type GetResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	state     protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
 	// TODO: Check if this is really needed. Perhaps a reference to the PND's ID
 	// is also sufficient.
-	Pnd *pnd.PrincipalNetworkDomain `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"`
-	Mne *ManagedNetworkElement      `protobuf:"bytes,3,opt,name=mne,proto3" json:"mne,omitempty"`
+	Pnd           *pnd.PrincipalNetworkDomain `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"`
+	Mne           *ManagedNetworkElement      `protobuf:"bytes,3,opt,name=mne,proto3" json:"mne,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetResponse) Reset() {
@@ -1039,13 +1028,12 @@ func (x *GetResponse) GetMne() *ManagedNetworkElement {
 }
 
 type GetFlattenedRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Mneid         string                 `protobuf:"bytes,2,opt,name=mneid,proto3" json:"mneid,omitempty"`
+	Pid           string                 `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Mneid     string `protobuf:"bytes,2,opt,name=mneid,proto3" json:"mneid,omitempty"`
-	Pid       string `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetFlattenedRequest) Reset() {
@@ -1100,15 +1088,14 @@ func (x *GetFlattenedRequest) GetPid() string {
 }
 
 type GetFlattenedResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	state     protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
 	// TODO: Check if this is really needed. Perhaps a reference to the PND's ID
 	// is also sufficient.
-	Pnd *pnd.PrincipalNetworkDomain     `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"`
-	Mne *FlattenedManagedNetworkElement `protobuf:"bytes,3,opt,name=mne,proto3" json:"mne,omitempty"`
+	Pnd           *pnd.PrincipalNetworkDomain     `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"`
+	Mne           *FlattenedManagedNetworkElement `protobuf:"bytes,3,opt,name=mne,proto3" json:"mne,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetFlattenedResponse) Reset() {
@@ -1163,10 +1150,7 @@ func (x *GetFlattenedResponse) GetMne() *FlattenedManagedNetworkElement {
 }
 
 type SetMne struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state              protoimpl.MessageState     `protogen:"open.v1"`
 	Address            string                     `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
 	Pid                string                     `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
 	PluginId           string                     `protobuf:"bytes,3,opt,name=pluginId,proto3" json:"pluginId,omitempty"`
@@ -1174,6 +1158,8 @@ type SetMne struct {
 	TransportOption    *transport.TransportOption `protobuf:"bytes,5,opt,name=transport_option,json=transportOption,proto3" json:"transport_option,omitempty"`
 	GnmiSubscribePaths []string                   `protobuf:"bytes,6,rep,name=gnmi_subscribe_paths,json=gnmiSubscribePaths,proto3" json:"gnmi_subscribe_paths,omitempty"`
 	MneId              string                     `protobuf:"bytes,7,opt,name=mne_id,json=mneId,proto3" json:"mne_id,omitempty"`
+	unknownFields      protoimpl.UnknownFields
+	sizeCache          protoimpl.SizeCache
 }
 
 func (x *SetMne) Reset() {
@@ -1256,13 +1242,12 @@ func (x *SetMne) GetMneId() string {
 }
 
 type AddListRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Mne           []*SetMne              `protobuf:"bytes,2,rep,name=mne,proto3" json:"mne,omitempty"`
+	Pid           string                 `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64     `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Mne       []*SetMne `protobuf:"bytes,2,rep,name=mne,proto3" json:"mne,omitempty"`
-	Pid       string    `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *AddListRequest) Reset() {
@@ -1317,12 +1302,11 @@ func (x *AddListRequest) GetPid() string {
 }
 
 type AddListResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Responses     []*SetResponse         `protobuf:"bytes,2,rep,name=responses,proto3" json:"responses,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64          `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Responses []*SetResponse `protobuf:"bytes,2,rep,name=responses,proto3" json:"responses,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *AddListResponse) Reset() {
@@ -1370,14 +1354,13 @@ func (x *AddListResponse) GetResponses() []*SetResponse {
 }
 
 type GetPathRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Mneid         string                 `protobuf:"bytes,2,opt,name=mneid,proto3" json:"mneid,omitempty"`
+	Path          string                 `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"`
+	Pid           string                 `protobuf:"bytes,4,opt,name=pid,proto3" json:"pid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Mneid     string `protobuf:"bytes,2,opt,name=mneid,proto3" json:"mneid,omitempty"`
-	Path      string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"`
-	Pid       string `protobuf:"bytes,4,opt,name=pid,proto3" json:"pid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetPathRequest) Reset() {
@@ -1439,15 +1422,14 @@ func (x *GetPathRequest) GetPid() string {
 }
 
 type GetPathResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	state     protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
 	// TODO: Check if this is really needed. Perhaps a reference to the PND's ID
 	// is also sufficient.
 	Pnd             *pnd.PrincipalNetworkDomain `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"`
 	MneNotification []*gnmi.Notification        `protobuf:"bytes,3,rep,name=mne_notification,json=mneNotification,proto3" json:"mne_notification,omitempty"`
+	unknownFields   protoimpl.UnknownFields
+	sizeCache       protoimpl.SizeCache
 }
 
 func (x *GetPathResponse) Reset() {
@@ -1502,14 +1484,13 @@ func (x *GetPathResponse) GetMneNotification() []*gnmi.Notification {
 }
 
 type GetIntendedPathRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Mneid         string                 `protobuf:"bytes,2,opt,name=mneid,proto3" json:"mneid,omitempty"`
+	IntendedPath  string                 `protobuf:"bytes,3,opt,name=intended_path,json=intendedPath,proto3" json:"intended_path,omitempty"`
+	Pid           string                 `protobuf:"bytes,4,opt,name=pid,proto3" json:"pid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp    int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Mneid        string `protobuf:"bytes,2,opt,name=mneid,proto3" json:"mneid,omitempty"`
-	IntendedPath string `protobuf:"bytes,3,opt,name=intended_path,json=intendedPath,proto3" json:"intended_path,omitempty"`
-	Pid          string `protobuf:"bytes,4,opt,name=pid,proto3" json:"pid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetIntendedPathRequest) Reset() {
@@ -1571,13 +1552,12 @@ func (x *GetIntendedPathRequest) GetPid() string {
 }
 
 type GetIntendedPathResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
+	state           protoimpl.MessageState      `protogen:"open.v1"`
 	Timestamp       int64                       `protobuf:"varint,64,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	Pnd             *pnd.PrincipalNetworkDomain `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"`
 	MneNotification []*gnmi.Notification        `protobuf:"bytes,3,rep,name=mne_notification,json=mneNotification,proto3" json:"mne_notification,omitempty"`
+	unknownFields   protoimpl.UnknownFields
+	sizeCache       protoimpl.SizeCache
 }
 
 func (x *GetIntendedPathResponse) Reset() {
@@ -1632,12 +1612,11 @@ func (x *GetIntendedPathResponse) GetMneNotification() []*gnmi.Notification {
 }
 
 type SetResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Id            string                 `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Id        string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *SetResponse) Reset() {
@@ -1685,13 +1664,12 @@ func (x *SetResponse) GetId() string {
 }
 
 type SetPathListRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	ChangeRequest []*ChangeRequest       `protobuf:"bytes,2,rep,name=change_request,json=changeRequest,proto3" json:"change_request,omitempty"`
+	Pid           string                 `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp     int64            `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	ChangeRequest []*ChangeRequest `protobuf:"bytes,2,rep,name=change_request,json=changeRequest,proto3" json:"change_request,omitempty"`
-	Pid           string           `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *SetPathListRequest) Reset() {
@@ -1746,12 +1724,11 @@ func (x *SetPathListRequest) GetPid() string {
 }
 
 type SetPathListResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Responses     []*SetResponse         `protobuf:"bytes,2,rep,name=responses,proto3" json:"responses,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64          `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Responses []*SetResponse `protobuf:"bytes,2,rep,name=responses,proto3" json:"responses,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *SetPathListResponse) Reset() {
@@ -1799,13 +1776,12 @@ func (x *SetPathListResponse) GetResponses() []*SetResponse {
 }
 
 type DeleteRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Pid           string                 `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
+	Mneid         string                 `protobuf:"bytes,3,opt,name=mneid,proto3" json:"mneid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Pid       string `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
-	Mneid     string `protobuf:"bytes,3,opt,name=mneid,proto3" json:"mneid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeleteRequest) Reset() {
@@ -1860,11 +1836,10 @@ func (x *DeleteRequest) GetMneid() string {
 }
 
 type DeleteResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeleteResponse) Reset() {
@@ -1905,14 +1880,13 @@ func (x *DeleteResponse) GetTimestamp() int64 {
 }
 
 type Change struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Id            string                 `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	Age           int64                  `protobuf:"varint,2,opt,name=age,proto3" json:"age,omitempty"`
+	State         ChangeState            `protobuf:"varint,3,opt,name=state,proto3,enum=gosdn.networkelement.ChangeState" json:"state,omitempty"`
+	Diff          *gnmi.Notification     `protobuf:"bytes,4,opt,name=diff,proto3" json:"diff,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Id    string             `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	Age   int64              `protobuf:"varint,2,opt,name=age,proto3" json:"age,omitempty"`
-	State ChangeState        `protobuf:"varint,3,opt,name=state,proto3,enum=gosdn.networkelement.ChangeState" json:"state,omitempty"`
-	Diff  *gnmi.Notification `protobuf:"bytes,4,opt,name=diff,proto3" json:"diff,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Change) Reset() {
@@ -1974,14 +1948,13 @@ func (x *Change) GetDiff() *gnmi.Notification {
 }
 
 type ChangeRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Mneid         string                 `protobuf:"bytes,1,opt,name=mneid,proto3" json:"mneid,omitempty"`
+	Path          *gnmi.Path             `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
+	Value         *gnmi.TypedValue       `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"`
+	ApiOp         ApiOperation           `protobuf:"varint,4,opt,name=api_op,json=apiOp,proto3,enum=gosdn.networkelement.ApiOperation" json:"api_op,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Mneid string           `protobuf:"bytes,1,opt,name=mneid,proto3" json:"mneid,omitempty"`
-	Path  *gnmi.Path       `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
-	Value *gnmi.TypedValue `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"`
-	ApiOp ApiOperation     `protobuf:"varint,4,opt,name=api_op,json=apiOp,proto3,enum=gosdn.networkelement.ApiOperation" json:"api_op,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *ChangeRequest) Reset() {
@@ -2043,12 +2016,11 @@ func (x *ChangeRequest) GetApiOp() ApiOperation {
 }
 
 type SetChange struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Cuid          string                 `protobuf:"bytes,1,opt,name=cuid,proto3" json:"cuid,omitempty"`
+	Op            Operation              `protobuf:"varint,2,opt,name=op,proto3,enum=gosdn.networkelement.Operation" json:"op,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Cuid string    `protobuf:"bytes,1,opt,name=cuid,proto3" json:"cuid,omitempty"`
-	Op   Operation `protobuf:"varint,2,opt,name=op,proto3,enum=gosdn.networkelement.Operation" json:"op,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *SetChange) Reset() {
@@ -2096,12 +2068,11 @@ func (x *SetChange) GetOp() Operation {
 }
 
 type GetChangeListRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Pid           string                 `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Pid       string `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetChangeListRequest) Reset() {
@@ -2149,15 +2120,14 @@ func (x *GetChangeListRequest) GetPid() string {
 }
 
 type GetChangeListResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	state     protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
 	// TODO: Check if this is really needed. Perhaps a reference to the PND's ID
 	// is also sufficient.
-	Pnd    *pnd.PrincipalNetworkDomain `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"`
-	Change []*Change                   `protobuf:"bytes,3,rep,name=change,proto3" json:"change,omitempty"`
+	Pnd           *pnd.PrincipalNetworkDomain `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"`
+	Change        []*Change                   `protobuf:"bytes,3,rep,name=change,proto3" json:"change,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetChangeListResponse) Reset() {
@@ -2212,13 +2182,12 @@ func (x *GetChangeListResponse) GetChange() []*Change {
 }
 
 type GetChangeRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Cuid          []string               `protobuf:"bytes,2,rep,name=cuid,proto3" json:"cuid,omitempty"`
+	Pid           string                 `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64    `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Cuid      []string `protobuf:"bytes,2,rep,name=cuid,proto3" json:"cuid,omitempty"`
-	Pid       string   `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetChangeRequest) Reset() {
@@ -2273,15 +2242,14 @@ func (x *GetChangeRequest) GetPid() string {
 }
 
 type GetChangeResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	state     protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
 	// TODO: Check if this is really needed. Perhaps a reference to the PND's ID
 	// is also sufficient.
-	Pnd    *pnd.PrincipalNetworkDomain `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"`
-	Change []*Change                   `protobuf:"bytes,3,rep,name=change,proto3" json:"change,omitempty"`
+	Pnd           *pnd.PrincipalNetworkDomain `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"`
+	Change        []*Change                   `protobuf:"bytes,3,rep,name=change,proto3" json:"change,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetChangeResponse) Reset() {
@@ -2336,13 +2304,12 @@ func (x *GetChangeResponse) GetChange() []*Change {
 }
 
 type SetChangeListRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Change        []*SetChange           `protobuf:"bytes,2,rep,name=change,proto3" json:"change,omitempty"`
+	Pid           string                 `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64        `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Change    []*SetChange `protobuf:"bytes,2,rep,name=change,proto3" json:"change,omitempty"`
-	Pid       string       `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *SetChangeListRequest) Reset() {
@@ -2397,12 +2364,11 @@ func (x *SetChangeListRequest) GetPid() string {
 }
 
 type SetChangeListResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Responses     []*SetResponse         `protobuf:"bytes,2,rep,name=responses,proto3" json:"responses,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64          `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Responses []*SetResponse `protobuf:"bytes,2,rep,name=responses,proto3" json:"responses,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *SetChangeListResponse) Reset() {
@@ -2452,12 +2418,11 @@ func (x *SetChangeListResponse) GetResponses() []*SetResponse {
 // The mode determines how the target should trigger updates to be sent.
 // Reference: gNMI Specification Section 3.5.1.2
 type SubscriptionList struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Subscription  []*Subscription        `protobuf:"bytes,1,rep,name=subscription,proto3" json:"subscription,omitempty"`
+	Mode          SubscriptionMode       `protobuf:"varint,2,opt,name=mode,proto3,enum=gosdn.networkelement.SubscriptionMode" json:"mode,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Subscription []*Subscription  `protobuf:"bytes,1,rep,name=subscription,proto3" json:"subscription,omitempty"`
-	Mode         SubscriptionMode `protobuf:"varint,2,opt,name=mode,proto3,enum=gosdn.networkelement.SubscriptionMode" json:"mode,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *SubscriptionList) Reset() {
@@ -2505,13 +2470,12 @@ func (x *SubscriptionList) GetMode() SubscriptionMode {
 }
 
 type Subscription struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Path           string     `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`
-	StreamMode     StreamMode `protobuf:"varint,2,opt,name=stream_mode,json=streamMode,proto3,enum=gosdn.networkelement.StreamMode" json:"stream_mode,omitempty"`
-	SampleInterval uint64     `protobuf:"varint,3,opt,name=sample_interval,json=sampleInterval,proto3" json:"sample_interval,omitempty"` // time in ns between samples in SAMPLE mode.
+	state          protoimpl.MessageState `protogen:"open.v1"`
+	Path           string                 `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`
+	StreamMode     StreamMode             `protobuf:"varint,2,opt,name=stream_mode,json=streamMode,proto3,enum=gosdn.networkelement.StreamMode" json:"stream_mode,omitempty"`
+	SampleInterval uint64                 `protobuf:"varint,3,opt,name=sample_interval,json=sampleInterval,proto3" json:"sample_interval,omitempty"` // time in ns between samples in SAMPLE mode.
+	unknownFields  protoimpl.UnknownFields
+	sizeCache      protoimpl.SizeCache
 }
 
 func (x *Subscription) Reset() {
@@ -2566,14 +2530,13 @@ func (x *Subscription) GetSampleInterval() uint64 {
 }
 
 type SubscribePathRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Mneid         string                 `protobuf:"bytes,2,opt,name=mneid,proto3" json:"mneid,omitempty"`
+	Pid           string                 `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"`
+	Sublist       *SubscriptionList      `protobuf:"bytes,4,opt,name=sublist,proto3" json:"sublist,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64             `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Mneid     string            `protobuf:"bytes,2,opt,name=mneid,proto3" json:"mneid,omitempty"`
-	Pid       string            `protobuf:"bytes,3,opt,name=pid,proto3" json:"pid,omitempty"`
-	Sublist   *SubscriptionList `protobuf:"bytes,4,opt,name=sublist,proto3" json:"sublist,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *SubscribePathRequest) Reset() {
@@ -2635,12 +2598,11 @@ func (x *SubscribePathRequest) GetSublist() *SubscriptionList {
 }
 
 type SubscribePathResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Timestamp       int64                `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	MneNotification []*gnmi.Notification `protobuf:"bytes,2,rep,name=mne_notification,json=mneNotification,proto3" json:"mne_notification,omitempty"`
+	state           protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp       int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	MneNotification []*gnmi.Notification   `protobuf:"bytes,2,rep,name=mne_notification,json=mneNotification,proto3" json:"mne_notification,omitempty"`
+	unknownFields   protoimpl.UnknownFields
+	sizeCache       protoimpl.SizeCache
 }
 
 func (x *SubscribePathResponse) Reset() {
@@ -2689,7 +2651,7 @@ func (x *SubscribePathResponse) GetMneNotification() []*gnmi.Notification {
 
 var File_gosdn_networkelement_networkelement_proto protoreflect.FileDescriptor
 
-var file_gosdn_networkelement_networkelement_proto_rawDesc = []byte{
+var file_gosdn_networkelement_networkelement_proto_rawDesc = string([]byte{
 	0x0a, 0x29, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x65,
 	0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x6c,
 	0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x14, 0x67, 0x6f, 0x73,
@@ -3212,16 +3174,16 @@ var file_gosdn_networkelement_networkelement_proto_rawDesc = []byte{
 	0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x77,
 	0x6f, 0x72, 0x6b, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
 	0x6f, 0x33,
-}
+})
 
 var (
 	file_gosdn_networkelement_networkelement_proto_rawDescOnce sync.Once
-	file_gosdn_networkelement_networkelement_proto_rawDescData = file_gosdn_networkelement_networkelement_proto_rawDesc
+	file_gosdn_networkelement_networkelement_proto_rawDescData []byte
 )
 
 func file_gosdn_networkelement_networkelement_proto_rawDescGZIP() []byte {
 	file_gosdn_networkelement_networkelement_proto_rawDescOnce.Do(func() {
-		file_gosdn_networkelement_networkelement_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdn_networkelement_networkelement_proto_rawDescData)
+		file_gosdn_networkelement_networkelement_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gosdn_networkelement_networkelement_proto_rawDesc), len(file_gosdn_networkelement_networkelement_proto_rawDesc)))
 	})
 	return file_gosdn_networkelement_networkelement_proto_rawDescData
 }
@@ -3367,7 +3329,7 @@ func file_gosdn_networkelement_networkelement_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdn_networkelement_networkelement_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_gosdn_networkelement_networkelement_proto_rawDesc), len(file_gosdn_networkelement_networkelement_proto_rawDesc)),
 			NumEnums:      5,
 			NumMessages:   39,
 			NumExtensions: 0,
@@ -3379,7 +3341,6 @@ func file_gosdn_networkelement_networkelement_proto_init() {
 		MessageInfos:      file_gosdn_networkelement_networkelement_proto_msgTypes,
 	}.Build()
 	File_gosdn_networkelement_networkelement_proto = out.File
-	file_gosdn_networkelement_networkelement_proto_rawDesc = nil
 	file_gosdn_networkelement_networkelement_proto_goTypes = nil
 	file_gosdn_networkelement_networkelement_proto_depIdxs = nil
 }
diff --git a/api/go/gosdn/networkelement/networkelement.pb.gw.go b/api/go/gosdn/networkelement/networkelement.pb.gw.go
index 642198688..409a3a5a4 100755
--- a/api/go/gosdn/networkelement/networkelement.pb.gw.go
+++ b/api/go/gosdn/networkelement/networkelement.pb.gw.go
@@ -10,6 +10,7 @@ package networkelement
 
 import (
 	"context"
+	"errors"
 	"io"
 	"net/http"
 
@@ -24,613 +25,488 @@ import (
 )
 
 // Suppress "imported and not used" errors
-var _ codes.Code
-var _ io.Reader
-var _ status.Status
-var _ = runtime.String
-var _ = utilities.NewDoubleArray
-var _ = metadata.Join
+var (
+	_ codes.Code
+	_ io.Reader
+	_ status.Status
+	_ = errors.New
+	_ = runtime.String
+	_ = utilities.NewDoubleArray
+	_ = metadata.Join
+)
 
 func request_NetworkElementService_Update_0(ctx context.Context, marshaler runtime.Marshaler, client NetworkElementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq UpdateNetworkElementRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq UpdateNetworkElementRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.Update(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_NetworkElementService_Update_0(ctx context.Context, marshaler runtime.Marshaler, server NetworkElementServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq UpdateNetworkElementRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq UpdateNetworkElementRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.Update(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_NetworkElementService_GetAllFlattened_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
-)
+var filter_NetworkElementService_GetAllFlattened_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
 
 func request_NetworkElementService_GetAllFlattened_0(ctx context.Context, marshaler runtime.Marshaler, client NetworkElementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetAllFlattenedRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq GetAllFlattenedRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NetworkElementService_GetAllFlattened_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.GetAllFlattened(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_NetworkElementService_GetAllFlattened_0(ctx context.Context, marshaler runtime.Marshaler, server NetworkElementServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetAllFlattenedRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq GetAllFlattenedRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NetworkElementService_GetAllFlattened_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.GetAllFlattened(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_NetworkElementService_Get_0 = &utilities.DoubleArray{Encoding: map[string]int{"mneid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
-)
+var filter_NetworkElementService_Get_0 = &utilities.DoubleArray{Encoding: map[string]int{"mneid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
 
 func request_NetworkElementService_Get_0(ctx context.Context, marshaler runtime.Marshaler, client NetworkElementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq GetRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["mneid"]
+	val, ok := pathParams["mneid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "mneid")
 	}
-
 	protoReq.Mneid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "mneid", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NetworkElementService_Get_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.Get(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_NetworkElementService_Get_0(ctx context.Context, marshaler runtime.Marshaler, server NetworkElementServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq GetRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["mneid"]
+	val, ok := pathParams["mneid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "mneid")
 	}
-
 	protoReq.Mneid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "mneid", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NetworkElementService_Get_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.Get(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_NetworkElementService_ParseYang_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
-)
+var filter_NetworkElementService_ParseYang_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
 
 func request_NetworkElementService_ParseYang_0(ctx context.Context, marshaler runtime.Marshaler, client NetworkElementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq ParseYangRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq ParseYangRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NetworkElementService_ParseYang_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.ParseYang(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_NetworkElementService_ParseYang_0(ctx context.Context, marshaler runtime.Marshaler, server NetworkElementServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq ParseYangRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq ParseYangRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NetworkElementService_ParseYang_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.ParseYang(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 func request_NetworkElementService_AddList_0(ctx context.Context, marshaler runtime.Marshaler, client NetworkElementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq AddListRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq AddListRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.AddList(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_NetworkElementService_AddList_0(ctx context.Context, marshaler runtime.Marshaler, server NetworkElementServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq AddListRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq AddListRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.AddList(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_NetworkElementService_GetPath_0 = &utilities.DoubleArray{Encoding: map[string]int{"mneid": 0, "path": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}}
-)
+var filter_NetworkElementService_GetPath_0 = &utilities.DoubleArray{Encoding: map[string]int{"mneid": 0, "path": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}}
 
 func request_NetworkElementService_GetPath_0(ctx context.Context, marshaler runtime.Marshaler, client NetworkElementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetPathRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq GetPathRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["mneid"]
+	val, ok := pathParams["mneid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "mneid")
 	}
-
 	protoReq.Mneid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "mneid", err)
 	}
-
 	val, ok = pathParams["path"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "path")
 	}
-
 	protoReq.Path, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "path", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NetworkElementService_GetPath_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.GetPath(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_NetworkElementService_GetPath_0(ctx context.Context, marshaler runtime.Marshaler, server NetworkElementServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetPathRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq GetPathRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["mneid"]
+	val, ok := pathParams["mneid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "mneid")
 	}
-
 	protoReq.Mneid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "mneid", err)
 	}
-
 	val, ok = pathParams["path"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "path")
 	}
-
 	protoReq.Path, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "path", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NetworkElementService_GetPath_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.GetPath(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_NetworkElementService_GetIntendedPath_0 = &utilities.DoubleArray{Encoding: map[string]int{"mneid": 0, "intended_path": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}}
-)
+var filter_NetworkElementService_GetIntendedPath_0 = &utilities.DoubleArray{Encoding: map[string]int{"mneid": 0, "intended_path": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}}
 
 func request_NetworkElementService_GetIntendedPath_0(ctx context.Context, marshaler runtime.Marshaler, client NetworkElementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetIntendedPathRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq GetIntendedPathRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["mneid"]
+	val, ok := pathParams["mneid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "mneid")
 	}
-
 	protoReq.Mneid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "mneid", err)
 	}
-
 	val, ok = pathParams["intended_path"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "intended_path")
 	}
-
 	protoReq.IntendedPath, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "intended_path", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NetworkElementService_GetIntendedPath_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.GetIntendedPath(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_NetworkElementService_GetIntendedPath_0(ctx context.Context, marshaler runtime.Marshaler, server NetworkElementServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetIntendedPathRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq GetIntendedPathRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["mneid"]
+	val, ok := pathParams["mneid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "mneid")
 	}
-
 	protoReq.Mneid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "mneid", err)
 	}
-
 	val, ok = pathParams["intended_path"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "intended_path")
 	}
-
 	protoReq.IntendedPath, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "intended_path", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NetworkElementService_GetIntendedPath_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.GetIntendedPath(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 func request_NetworkElementService_SetPathList_0(ctx context.Context, marshaler runtime.Marshaler, client NetworkElementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq SetPathListRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq SetPathListRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.SetPathList(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_NetworkElementService_SetPathList_0(ctx context.Context, marshaler runtime.Marshaler, server NetworkElementServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq SetPathListRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq SetPathListRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.SetPathList(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_NetworkElementService_Delete_0 = &utilities.DoubleArray{Encoding: map[string]int{"mneid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
-)
+var filter_NetworkElementService_Delete_0 = &utilities.DoubleArray{Encoding: map[string]int{"mneid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
 
 func request_NetworkElementService_Delete_0(ctx context.Context, marshaler runtime.Marshaler, client NetworkElementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeleteRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq DeleteRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["mneid"]
+	val, ok := pathParams["mneid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "mneid")
 	}
-
 	protoReq.Mneid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "mneid", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NetworkElementService_Delete_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.Delete(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_NetworkElementService_Delete_0(ctx context.Context, marshaler runtime.Marshaler, server NetworkElementServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeleteRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq DeleteRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["mneid"]
+	val, ok := pathParams["mneid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "mneid")
 	}
-
 	protoReq.Mneid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "mneid", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NetworkElementService_Delete_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.Delete(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_NetworkElementService_GetChangeList_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
-)
+var filter_NetworkElementService_GetChangeList_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
 
 func request_NetworkElementService_GetChangeList_0(ctx context.Context, marshaler runtime.Marshaler, client NetworkElementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetChangeListRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq GetChangeListRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NetworkElementService_GetChangeList_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.GetChangeList(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_NetworkElementService_GetChangeList_0(ctx context.Context, marshaler runtime.Marshaler, server NetworkElementServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetChangeListRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq GetChangeListRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NetworkElementService_GetChangeList_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.GetChangeList(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_NetworkElementService_GetChange_0 = &utilities.DoubleArray{Encoding: map[string]int{"cuid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
-)
+var filter_NetworkElementService_GetChange_0 = &utilities.DoubleArray{Encoding: map[string]int{"cuid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
 
 func request_NetworkElementService_GetChange_0(ctx context.Context, marshaler runtime.Marshaler, client NetworkElementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetChangeRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq GetChangeRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["cuid"]
+	val, ok := pathParams["cuid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "cuid")
 	}
-
 	protoReq.Cuid, err = runtime.StringSlice(val, ",")
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "cuid", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NetworkElementService_GetChange_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.GetChange(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_NetworkElementService_GetChange_0(ctx context.Context, marshaler runtime.Marshaler, server NetworkElementServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetChangeRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq GetChangeRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["cuid"]
+	val, ok := pathParams["cuid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "cuid")
 	}
-
 	protoReq.Cuid, err = runtime.StringSlice(val, ",")
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "cuid", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_NetworkElementService_GetChange_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.GetChange(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 func request_NetworkElementService_SetChangeList_0(ctx context.Context, marshaler runtime.Marshaler, client NetworkElementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq SetChangeListRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq SetChangeListRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.SetChangeList(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_NetworkElementService_SetChangeList_0(ctx context.Context, marshaler runtime.Marshaler, server NetworkElementServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq SetChangeListRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq SetChangeListRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.SetChangeList(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 // RegisterNetworkElementServiceHandlerServer registers the http handlers for service NetworkElementService to "mux".
@@ -639,16 +515,13 @@ func local_request_NetworkElementService_SetChangeList_0(ctx context.Context, ma
 // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterNetworkElementServiceHandlerFromEndpoint instead.
 // GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
 func RegisterNetworkElementServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server NetworkElementServiceServer) error {
-
-	mux.Handle("POST", pattern_NetworkElementService_Update_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_NetworkElementService_Update_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/Update", runtime.WithHTTPPathPattern("/network-element/update"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/Update", runtime.WithHTTPPathPattern("/network-element/update"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -660,20 +533,15 @@ func RegisterNetworkElementServiceHandlerServer(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_Update_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_NetworkElementService_GetAllFlattened_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_NetworkElementService_GetAllFlattened_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/GetAllFlattened", runtime.WithHTTPPathPattern("/mnes"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/GetAllFlattened", runtime.WithHTTPPathPattern("/mnes"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -685,20 +553,15 @@ func RegisterNetworkElementServiceHandlerServer(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_GetAllFlattened_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_NetworkElementService_Get_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_NetworkElementService_Get_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/Get", runtime.WithHTTPPathPattern("/mnes/{mneid}"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/Get", runtime.WithHTTPPathPattern("/mnes/{mneid}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -710,20 +573,15 @@ func RegisterNetworkElementServiceHandlerServer(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_Get_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_NetworkElementService_ParseYang_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_NetworkElementService_ParseYang_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/ParseYang", runtime.WithHTTPPathPattern("/yang/parse"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/ParseYang", runtime.WithHTTPPathPattern("/yang/parse"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -735,20 +593,15 @@ func RegisterNetworkElementServiceHandlerServer(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_ParseYang_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_NetworkElementService_AddList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_NetworkElementService_AddList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/AddList", runtime.WithHTTPPathPattern("/mnes"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/AddList", runtime.WithHTTPPathPattern("/mnes"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -760,20 +613,15 @@ func RegisterNetworkElementServiceHandlerServer(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_AddList_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_NetworkElementService_GetPath_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_NetworkElementService_GetPath_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/GetPath", runtime.WithHTTPPathPattern("/mnes/{mneid}/paths/{path}"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/GetPath", runtime.WithHTTPPathPattern("/mnes/{mneid}/paths/{path}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -785,20 +633,15 @@ func RegisterNetworkElementServiceHandlerServer(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_GetPath_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_NetworkElementService_GetIntendedPath_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_NetworkElementService_GetIntendedPath_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/GetIntendedPath", runtime.WithHTTPPathPattern("/mnes/{mneid}/intendedpaths/{intended_path}"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/GetIntendedPath", runtime.WithHTTPPathPattern("/mnes/{mneid}/intendedpaths/{intended_path}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -810,20 +653,15 @@ func RegisterNetworkElementServiceHandlerServer(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_GetIntendedPath_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_NetworkElementService_SetPathList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_NetworkElementService_SetPathList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/SetPathList", runtime.WithHTTPPathPattern("/mnes/paths"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/SetPathList", runtime.WithHTTPPathPattern("/mnes/paths"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -835,20 +673,15 @@ func RegisterNetworkElementServiceHandlerServer(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_SetPathList_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_NetworkElementService_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_NetworkElementService_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/Delete", runtime.WithHTTPPathPattern("/mnes/{mneid}"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/Delete", runtime.WithHTTPPathPattern("/mnes/{mneid}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -860,20 +693,15 @@ func RegisterNetworkElementServiceHandlerServer(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_Delete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_NetworkElementService_GetChangeList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_NetworkElementService_GetChangeList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/GetChangeList", runtime.WithHTTPPathPattern("/mnes/changes"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/GetChangeList", runtime.WithHTTPPathPattern("/mnes/changes"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -885,20 +713,15 @@ func RegisterNetworkElementServiceHandlerServer(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_GetChangeList_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_NetworkElementService_GetChange_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_NetworkElementService_GetChange_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/GetChange", runtime.WithHTTPPathPattern("/mnes/changes/{cuid}"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/GetChange", runtime.WithHTTPPathPattern("/mnes/changes/{cuid}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -910,20 +733,15 @@ func RegisterNetworkElementServiceHandlerServer(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_GetChange_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_NetworkElementService_SetChangeList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_NetworkElementService_SetChangeList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/SetChangeList", runtime.WithHTTPPathPattern("/mnes/changes"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/SetChangeList", runtime.WithHTTPPathPattern("/mnes/changes"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -935,9 +753,7 @@ func RegisterNetworkElementServiceHandlerServer(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_SetChangeList_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
 
 	return nil
@@ -964,7 +780,6 @@ func RegisterNetworkElementServiceHandlerFromEndpoint(ctx context.Context, mux *
 			}
 		}()
 	}()
-
 	return RegisterNetworkElementServiceHandler(ctx, mux, conn)
 }
 
@@ -980,14 +795,11 @@ func RegisterNetworkElementServiceHandler(ctx context.Context, mux *runtime.Serv
 // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
 // "NetworkElementServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares.
 func RegisterNetworkElementServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client NetworkElementServiceClient) error {
-
-	mux.Handle("POST", pattern_NetworkElementService_Update_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_NetworkElementService_Update_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/Update", runtime.WithHTTPPathPattern("/network-element/update"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/Update", runtime.WithHTTPPathPattern("/network-element/update"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -998,18 +810,13 @@ func RegisterNetworkElementServiceHandlerClient(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_Update_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_NetworkElementService_GetAllFlattened_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_NetworkElementService_GetAllFlattened_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/GetAllFlattened", runtime.WithHTTPPathPattern("/mnes"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/GetAllFlattened", runtime.WithHTTPPathPattern("/mnes"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -1020,18 +827,13 @@ func RegisterNetworkElementServiceHandlerClient(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_GetAllFlattened_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_NetworkElementService_Get_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_NetworkElementService_Get_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/Get", runtime.WithHTTPPathPattern("/mnes/{mneid}"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/Get", runtime.WithHTTPPathPattern("/mnes/{mneid}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -1042,18 +844,13 @@ func RegisterNetworkElementServiceHandlerClient(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_Get_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_NetworkElementService_ParseYang_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_NetworkElementService_ParseYang_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/ParseYang", runtime.WithHTTPPathPattern("/yang/parse"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/ParseYang", runtime.WithHTTPPathPattern("/yang/parse"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -1064,18 +861,13 @@ func RegisterNetworkElementServiceHandlerClient(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_ParseYang_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_NetworkElementService_AddList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_NetworkElementService_AddList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/AddList", runtime.WithHTTPPathPattern("/mnes"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/AddList", runtime.WithHTTPPathPattern("/mnes"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -1086,18 +878,13 @@ func RegisterNetworkElementServiceHandlerClient(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_AddList_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_NetworkElementService_GetPath_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_NetworkElementService_GetPath_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/GetPath", runtime.WithHTTPPathPattern("/mnes/{mneid}/paths/{path}"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/GetPath", runtime.WithHTTPPathPattern("/mnes/{mneid}/paths/{path}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -1108,18 +895,13 @@ func RegisterNetworkElementServiceHandlerClient(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_GetPath_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_NetworkElementService_GetIntendedPath_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_NetworkElementService_GetIntendedPath_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/GetIntendedPath", runtime.WithHTTPPathPattern("/mnes/{mneid}/intendedpaths/{intended_path}"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/GetIntendedPath", runtime.WithHTTPPathPattern("/mnes/{mneid}/intendedpaths/{intended_path}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -1130,18 +912,13 @@ func RegisterNetworkElementServiceHandlerClient(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_GetIntendedPath_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_NetworkElementService_SetPathList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_NetworkElementService_SetPathList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/SetPathList", runtime.WithHTTPPathPattern("/mnes/paths"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/SetPathList", runtime.WithHTTPPathPattern("/mnes/paths"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -1152,18 +929,13 @@ func RegisterNetworkElementServiceHandlerClient(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_SetPathList_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_NetworkElementService_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_NetworkElementService_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/Delete", runtime.WithHTTPPathPattern("/mnes/{mneid}"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/Delete", runtime.WithHTTPPathPattern("/mnes/{mneid}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -1174,18 +946,13 @@ func RegisterNetworkElementServiceHandlerClient(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_Delete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_NetworkElementService_GetChangeList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_NetworkElementService_GetChangeList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/GetChangeList", runtime.WithHTTPPathPattern("/mnes/changes"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/GetChangeList", runtime.WithHTTPPathPattern("/mnes/changes"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -1196,18 +963,13 @@ func RegisterNetworkElementServiceHandlerClient(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_GetChangeList_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_NetworkElementService_GetChange_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_NetworkElementService_GetChange_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/GetChange", runtime.WithHTTPPathPattern("/mnes/changes/{cuid}"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/GetChange", runtime.WithHTTPPathPattern("/mnes/changes/{cuid}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -1218,18 +980,13 @@ func RegisterNetworkElementServiceHandlerClient(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_GetChange_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_NetworkElementService_SetChangeList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_NetworkElementService_SetChangeList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/SetChangeList", runtime.WithHTTPPathPattern("/mnes/changes"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.networkelement.NetworkElementService/SetChangeList", runtime.WithHTTPPathPattern("/mnes/changes"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -1240,62 +997,37 @@ func RegisterNetworkElementServiceHandlerClient(ctx context.Context, mux *runtim
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_NetworkElementService_SetChangeList_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
 	return nil
 }
 
 var (
-	pattern_NetworkElementService_Update_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"network-element", "update"}, ""))
-
+	pattern_NetworkElementService_Update_0          = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"network-element", "update"}, ""))
 	pattern_NetworkElementService_GetAllFlattened_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"mnes"}, ""))
-
-	pattern_NetworkElementService_Get_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"mnes", "mneid"}, ""))
-
-	pattern_NetworkElementService_ParseYang_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"yang", "parse"}, ""))
-
-	pattern_NetworkElementService_AddList_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"mnes"}, ""))
-
-	pattern_NetworkElementService_GetPath_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"mnes", "mneid", "paths", "path"}, ""))
-
+	pattern_NetworkElementService_Get_0             = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"mnes", "mneid"}, ""))
+	pattern_NetworkElementService_ParseYang_0       = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"yang", "parse"}, ""))
+	pattern_NetworkElementService_AddList_0         = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"mnes"}, ""))
+	pattern_NetworkElementService_GetPath_0         = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"mnes", "mneid", "paths", "path"}, ""))
 	pattern_NetworkElementService_GetIntendedPath_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"mnes", "mneid", "intendedpaths", "intended_path"}, ""))
-
-	pattern_NetworkElementService_SetPathList_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"mnes", "paths"}, ""))
-
-	pattern_NetworkElementService_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"mnes", "mneid"}, ""))
-
-	pattern_NetworkElementService_GetChangeList_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"mnes", "changes"}, ""))
-
-	pattern_NetworkElementService_GetChange_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"mnes", "changes", "cuid"}, ""))
-
-	pattern_NetworkElementService_SetChangeList_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"mnes", "changes"}, ""))
+	pattern_NetworkElementService_SetPathList_0     = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"mnes", "paths"}, ""))
+	pattern_NetworkElementService_Delete_0          = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"mnes", "mneid"}, ""))
+	pattern_NetworkElementService_GetChangeList_0   = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"mnes", "changes"}, ""))
+	pattern_NetworkElementService_GetChange_0       = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"mnes", "changes", "cuid"}, ""))
+	pattern_NetworkElementService_SetChangeList_0   = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"mnes", "changes"}, ""))
 )
 
 var (
-	forward_NetworkElementService_Update_0 = runtime.ForwardResponseMessage
-
+	forward_NetworkElementService_Update_0          = runtime.ForwardResponseMessage
 	forward_NetworkElementService_GetAllFlattened_0 = runtime.ForwardResponseMessage
-
-	forward_NetworkElementService_Get_0 = runtime.ForwardResponseMessage
-
-	forward_NetworkElementService_ParseYang_0 = runtime.ForwardResponseMessage
-
-	forward_NetworkElementService_AddList_0 = runtime.ForwardResponseMessage
-
-	forward_NetworkElementService_GetPath_0 = runtime.ForwardResponseMessage
-
+	forward_NetworkElementService_Get_0             = runtime.ForwardResponseMessage
+	forward_NetworkElementService_ParseYang_0       = runtime.ForwardResponseMessage
+	forward_NetworkElementService_AddList_0         = runtime.ForwardResponseMessage
+	forward_NetworkElementService_GetPath_0         = runtime.ForwardResponseMessage
 	forward_NetworkElementService_GetIntendedPath_0 = runtime.ForwardResponseMessage
-
-	forward_NetworkElementService_SetPathList_0 = runtime.ForwardResponseMessage
-
-	forward_NetworkElementService_Delete_0 = runtime.ForwardResponseMessage
-
-	forward_NetworkElementService_GetChangeList_0 = runtime.ForwardResponseMessage
-
-	forward_NetworkElementService_GetChange_0 = runtime.ForwardResponseMessage
-
-	forward_NetworkElementService_SetChangeList_0 = runtime.ForwardResponseMessage
+	forward_NetworkElementService_SetPathList_0     = runtime.ForwardResponseMessage
+	forward_NetworkElementService_Delete_0          = runtime.ForwardResponseMessage
+	forward_NetworkElementService_GetChangeList_0   = runtime.ForwardResponseMessage
+	forward_NetworkElementService_GetChange_0       = runtime.ForwardResponseMessage
+	forward_NetworkElementService_SetChangeList_0   = runtime.ForwardResponseMessage
 )
diff --git a/api/go/gosdn/plugin-internal/plugin-internal.pb.go b/api/go/gosdn/plugin-internal/plugin-internal.pb.go
index 490d4f78c..6d52ec6b0 100755
--- a/api/go/gosdn/plugin-internal/plugin-internal.pb.go
+++ b/api/go/gosdn/plugin-internal/plugin-internal.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: gosdn/plugin-internal/plugin-internal.proto
 
@@ -9,10 +9,12 @@ package plugin_internal
 import (
 	_ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate"
 	plugin_registry "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/plugin-registry"
+	_ "google.golang.org/genproto/googleapis/api/annotations"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -23,11 +25,10 @@ const (
 )
 
 type GetAvailablePluginsRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetAvailablePluginsRequest) Reset() {
@@ -67,29 +68,28 @@ func (x *GetAvailablePluginsRequest) GetTimestamp() int64 {
 	return 0
 }
 
-type GetAvailablePluginsResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+type GetPluginSchemaRequest struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Pid           string                 `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64                     `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Plugins   []*plugin_registry.Plugin `protobuf:"bytes,2,rep,name=plugins,proto3" json:"plugins,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
-func (x *GetAvailablePluginsResponse) Reset() {
-	*x = GetAvailablePluginsResponse{}
+func (x *GetPluginSchemaRequest) Reset() {
+	*x = GetPluginSchemaRequest{}
 	mi := &file_gosdn_plugin_internal_plugin_internal_proto_msgTypes[1]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
 
-func (x *GetAvailablePluginsResponse) String() string {
+func (x *GetPluginSchemaRequest) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*GetAvailablePluginsResponse) ProtoMessage() {}
+func (*GetPluginSchemaRequest) ProtoMessage() {}
 
-func (x *GetAvailablePluginsResponse) ProtoReflect() protoreflect.Message {
+func (x *GetPluginSchemaRequest) ProtoReflect() protoreflect.Message {
 	mi := &file_gosdn_plugin_internal_plugin_internal_proto_msgTypes[1]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -101,48 +101,46 @@ func (x *GetAvailablePluginsResponse) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use GetAvailablePluginsResponse.ProtoReflect.Descriptor instead.
-func (*GetAvailablePluginsResponse) Descriptor() ([]byte, []int) {
+// Deprecated: Use GetPluginSchemaRequest.ProtoReflect.Descriptor instead.
+func (*GetPluginSchemaRequest) Descriptor() ([]byte, []int) {
 	return file_gosdn_plugin_internal_plugin_internal_proto_rawDescGZIP(), []int{1}
 }
 
-func (x *GetAvailablePluginsResponse) GetTimestamp() int64 {
+func (x *GetPluginSchemaRequest) GetTimestamp() int64 {
 	if x != nil {
 		return x.Timestamp
 	}
 	return 0
 }
 
-func (x *GetAvailablePluginsResponse) GetPlugins() []*plugin_registry.Plugin {
+func (x *GetPluginSchemaRequest) GetPid() string {
 	if x != nil {
-		return x.Plugins
+		return x.Pid
 	}
-	return nil
+	return ""
 }
 
-type GetPluginSchemaRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+type PluginSchemaPayload struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Chunk         []byte                 `protobuf:"bytes,1,opt,name=chunk,proto3" json:"chunk,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Pid       string `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
-func (x *GetPluginSchemaRequest) Reset() {
-	*x = GetPluginSchemaRequest{}
+func (x *PluginSchemaPayload) Reset() {
+	*x = PluginSchemaPayload{}
 	mi := &file_gosdn_plugin_internal_plugin_internal_proto_msgTypes[2]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
 
-func (x *GetPluginSchemaRequest) String() string {
+func (x *PluginSchemaPayload) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*GetPluginSchemaRequest) ProtoMessage() {}
+func (*PluginSchemaPayload) ProtoMessage() {}
 
-func (x *GetPluginSchemaRequest) ProtoReflect() protoreflect.Message {
+func (x *PluginSchemaPayload) ProtoReflect() protoreflect.Message {
 	mi := &file_gosdn_plugin_internal_plugin_internal_proto_msgTypes[2]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -154,47 +152,40 @@ func (x *GetPluginSchemaRequest) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use GetPluginSchemaRequest.ProtoReflect.Descriptor instead.
-func (*GetPluginSchemaRequest) Descriptor() ([]byte, []int) {
+// Deprecated: Use PluginSchemaPayload.ProtoReflect.Descriptor instead.
+func (*PluginSchemaPayload) Descriptor() ([]byte, []int) {
 	return file_gosdn_plugin_internal_plugin_internal_proto_rawDescGZIP(), []int{2}
 }
 
-func (x *GetPluginSchemaRequest) GetTimestamp() int64 {
-	if x != nil {
-		return x.Timestamp
-	}
-	return 0
-}
-
-func (x *GetPluginSchemaRequest) GetPid() string {
+func (x *PluginSchemaPayload) GetChunk() []byte {
 	if x != nil {
-		return x.Pid
+		return x.Chunk
 	}
-	return ""
+	return nil
 }
 
-type PluginSchemaPayload struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+type GetAvailablePluginsResponse struct {
+	state         protoimpl.MessageState    `protogen:"open.v1"`
+	Timestamp     int64                     `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Plugins       []*plugin_registry.Plugin `protobuf:"bytes,2,rep,name=plugins,proto3" json:"plugins,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Chunk []byte `protobuf:"bytes,1,opt,name=chunk,proto3" json:"chunk,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
-func (x *PluginSchemaPayload) Reset() {
-	*x = PluginSchemaPayload{}
+func (x *GetAvailablePluginsResponse) Reset() {
+	*x = GetAvailablePluginsResponse{}
 	mi := &file_gosdn_plugin_internal_plugin_internal_proto_msgTypes[3]
 	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 	ms.StoreMessageInfo(mi)
 }
 
-func (x *PluginSchemaPayload) String() string {
+func (x *GetAvailablePluginsResponse) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*PluginSchemaPayload) ProtoMessage() {}
+func (*GetAvailablePluginsResponse) ProtoMessage() {}
 
-func (x *PluginSchemaPayload) ProtoReflect() protoreflect.Message {
+func (x *GetAvailablePluginsResponse) ProtoReflect() protoreflect.Message {
 	mi := &file_gosdn_plugin_internal_plugin_internal_proto_msgTypes[3]
 	if x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -206,21 +197,28 @@ func (x *PluginSchemaPayload) ProtoReflect() protoreflect.Message {
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use PluginSchemaPayload.ProtoReflect.Descriptor instead.
-func (*PluginSchemaPayload) Descriptor() ([]byte, []int) {
+// Deprecated: Use GetAvailablePluginsResponse.ProtoReflect.Descriptor instead.
+func (*GetAvailablePluginsResponse) Descriptor() ([]byte, []int) {
 	return file_gosdn_plugin_internal_plugin_internal_proto_rawDescGZIP(), []int{3}
 }
 
-func (x *PluginSchemaPayload) GetChunk() []byte {
+func (x *GetAvailablePluginsResponse) GetTimestamp() int64 {
 	if x != nil {
-		return x.Chunk
+		return x.Timestamp
+	}
+	return 0
+}
+
+func (x *GetAvailablePluginsResponse) GetPlugins() []*plugin_registry.Plugin {
+	if x != nil {
+		return x.Plugins
 	}
 	return nil
 }
 
 var File_gosdn_plugin_internal_plugin_internal_proto protoreflect.FileDescriptor
 
-var file_gosdn_plugin_internal_plugin_internal_proto_rawDesc = []byte{
+var file_gosdn_plugin_internal_plugin_internal_proto_rawDesc = string([]byte{
 	0x0a, 0x2b, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2d, 0x69,
 	0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2d, 0x69,
 	0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x67,
@@ -229,56 +227,66 @@ var file_gosdn_plugin_internal_plugin_internal_proto_rawDesc = []byte{
 	0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
 	0x6f, 0x1a, 0x2b, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2d,
 	0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2d,
-	0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x3a,
-	0x0a, 0x1a, 0x47, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x6c,
-	0x75, 0x67, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09,
-	0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
-	0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x74, 0x0a, 0x1b, 0x47, 0x65,
-	0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e,
-	0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d,
-	0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69,
-	0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x37, 0x0a, 0x07, 0x70, 0x6c, 0x75, 0x67, 0x69,
-	0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e,
-	0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79,
-	0x2e, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x52, 0x07, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73,
-	0x22, 0x50, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x53, 0x63, 0x68,
-	0x65, 0x6d, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69,
+	0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c,
+	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74,
+	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x3a, 0x0a, 0x1a,
+	0x47, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x6c, 0x75, 0x67,
+	0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69,
 	0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74,
-	0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x18, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x03, 0x70,
-	0x69, 0x64, 0x22, 0x2b, 0x0a, 0x13, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x53, 0x63, 0x68, 0x65,
-	0x6d, 0x61, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x75,
-	0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x32,
-	0xf2, 0x01, 0x0a, 0x15, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
-	0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x69, 0x0a, 0x10, 0x41, 0x76, 0x61,
-	0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x12, 0x31, 0x2e,
-	0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x74,
-	0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62,
-	0x6c, 0x65, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x22, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f,
-	0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x50, 0x6c, 0x75, 0x67, 0x69,
-	0x6e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x2d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e,
-	0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e,
-	0x47, 0x65, 0x74, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52,
-	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70,
-	0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x50,
-	0x6c, 0x75, 0x67, 0x69, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x50, 0x61, 0x79, 0x6c, 0x6f,
-	0x61, 0x64, 0x30, 0x01, 0x42, 0x3b, 0x5a, 0x39, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x66, 0x62, 0x69,
-	0x2e, 0x68, 0x2d, 0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67,
-	0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64,
-	0x6e, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
-	0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+	0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x50, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x50,
+	0x6c, 0x75, 0x67, 0x69, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
+	0x12, 0x18, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba,
+	0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, 0x2b, 0x0a, 0x13, 0x50, 0x6c,
+	0x75, 0x67, 0x69, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61,
+	0x64, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c,
+	0x52, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x22, 0x74, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x41, 0x76,
+	0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x52, 0x65,
+	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74,
+	0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73,
+	0x74, 0x61, 0x6d, 0x70, 0x12, 0x37, 0x0a, 0x07, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x18,
+	0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c,
+	0x75, 0x67, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x50, 0x6c,
+	0x75, 0x67, 0x69, 0x6e, 0x52, 0x07, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x32, 0xf2, 0x02,
+	0x0a, 0x15, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
+	0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x69, 0x0a, 0x10, 0x41, 0x76, 0x61, 0x69, 0x6c,
+	0x61, 0x62, 0x6c, 0x65, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x12, 0x31, 0x2e, 0x67, 0x6f,
+	0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72,
+	0x6e, 0x61, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65,
+	0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22,
+	0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x72, 0x65,
+	0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x53,
+	0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x2d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c,
+	0x75, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x47, 0x65,
+	0x74, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75,
+	0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x50, 0x6c, 0x75,
+	0x67, 0x69, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64,
+	0x30, 0x01, 0x12, 0x7e, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62,
+	0x6c, 0x65, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x12, 0x31, 0x2e, 0x67, 0x6f, 0x73, 0x64,
+	0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
+	0x6c, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x6c,
+	0x75, 0x67, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x67,
+	0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x67, 0x69,
+	0x73, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x22, 0x10, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69,
+	0x6e, 0x73, 0x42, 0x3b, 0x5a, 0x39, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x66, 0x62, 0x69, 0x2e, 0x68,
+	0x2d, 0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67, 0x6f, 0x73,
+	0x64, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f,
+	0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x62,
+	0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+})
 
 var (
 	file_gosdn_plugin_internal_plugin_internal_proto_rawDescOnce sync.Once
-	file_gosdn_plugin_internal_plugin_internal_proto_rawDescData = file_gosdn_plugin_internal_plugin_internal_proto_rawDesc
+	file_gosdn_plugin_internal_plugin_internal_proto_rawDescData []byte
 )
 
 func file_gosdn_plugin_internal_plugin_internal_proto_rawDescGZIP() []byte {
 	file_gosdn_plugin_internal_plugin_internal_proto_rawDescOnce.Do(func() {
-		file_gosdn_plugin_internal_plugin_internal_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdn_plugin_internal_plugin_internal_proto_rawDescData)
+		file_gosdn_plugin_internal_plugin_internal_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gosdn_plugin_internal_plugin_internal_proto_rawDesc), len(file_gosdn_plugin_internal_plugin_internal_proto_rawDesc)))
 	})
 	return file_gosdn_plugin_internal_plugin_internal_proto_rawDescData
 }
@@ -286,20 +294,22 @@ func file_gosdn_plugin_internal_plugin_internal_proto_rawDescGZIP() []byte {
 var file_gosdn_plugin_internal_plugin_internal_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
 var file_gosdn_plugin_internal_plugin_internal_proto_goTypes = []any{
 	(*GetAvailablePluginsRequest)(nil),  // 0: gosdn.plugin_internal.GetAvailablePluginsRequest
-	(*GetAvailablePluginsResponse)(nil), // 1: gosdn.plugin_internal.GetAvailablePluginsResponse
-	(*GetPluginSchemaRequest)(nil),      // 2: gosdn.plugin_internal.GetPluginSchemaRequest
-	(*PluginSchemaPayload)(nil),         // 3: gosdn.plugin_internal.PluginSchemaPayload
+	(*GetPluginSchemaRequest)(nil),      // 1: gosdn.plugin_internal.GetPluginSchemaRequest
+	(*PluginSchemaPayload)(nil),         // 2: gosdn.plugin_internal.PluginSchemaPayload
+	(*GetAvailablePluginsResponse)(nil), // 3: gosdn.plugin_internal.GetAvailablePluginsResponse
 	(*plugin_registry.Plugin)(nil),      // 4: gosdn.plugin_registry.Plugin
 	(*plugin_registry.GetResponse)(nil), // 5: gosdn.plugin_registry.GetResponse
 }
 var file_gosdn_plugin_internal_plugin_internal_proto_depIdxs = []int32{
 	4, // 0: gosdn.plugin_internal.GetAvailablePluginsResponse.plugins:type_name -> gosdn.plugin_registry.Plugin
 	0, // 1: gosdn.plugin_internal.PluginInternalService.AvailablePlugins:input_type -> gosdn.plugin_internal.GetAvailablePluginsRequest
-	2, // 2: gosdn.plugin_internal.PluginInternalService.GetPluginSchema:input_type -> gosdn.plugin_internal.GetPluginSchemaRequest
-	5, // 3: gosdn.plugin_internal.PluginInternalService.AvailablePlugins:output_type -> gosdn.plugin_registry.GetResponse
-	3, // 4: gosdn.plugin_internal.PluginInternalService.GetPluginSchema:output_type -> gosdn.plugin_internal.PluginSchemaPayload
-	3, // [3:5] is the sub-list for method output_type
-	1, // [1:3] is the sub-list for method input_type
+	1, // 2: gosdn.plugin_internal.PluginInternalService.GetPluginSchema:input_type -> gosdn.plugin_internal.GetPluginSchemaRequest
+	0, // 3: gosdn.plugin_internal.PluginInternalService.GetAvailablePlugins:input_type -> gosdn.plugin_internal.GetAvailablePluginsRequest
+	5, // 4: gosdn.plugin_internal.PluginInternalService.AvailablePlugins:output_type -> gosdn.plugin_registry.GetResponse
+	2, // 5: gosdn.plugin_internal.PluginInternalService.GetPluginSchema:output_type -> gosdn.plugin_internal.PluginSchemaPayload
+	5, // 6: gosdn.plugin_internal.PluginInternalService.GetAvailablePlugins:output_type -> gosdn.plugin_registry.GetResponse
+	4, // [4:7] is the sub-list for method output_type
+	1, // [1:4] is the sub-list for method input_type
 	1, // [1:1] is the sub-list for extension type_name
 	1, // [1:1] is the sub-list for extension extendee
 	0, // [0:1] is the sub-list for field type_name
@@ -314,7 +324,7 @@ func file_gosdn_plugin_internal_plugin_internal_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdn_plugin_internal_plugin_internal_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_gosdn_plugin_internal_plugin_internal_proto_rawDesc), len(file_gosdn_plugin_internal_plugin_internal_proto_rawDesc)),
 			NumEnums:      0,
 			NumMessages:   4,
 			NumExtensions: 0,
@@ -325,7 +335,6 @@ func file_gosdn_plugin_internal_plugin_internal_proto_init() {
 		MessageInfos:      file_gosdn_plugin_internal_plugin_internal_proto_msgTypes,
 	}.Build()
 	File_gosdn_plugin_internal_plugin_internal_proto = out.File
-	file_gosdn_plugin_internal_plugin_internal_proto_rawDesc = nil
 	file_gosdn_plugin_internal_plugin_internal_proto_goTypes = nil
 	file_gosdn_plugin_internal_plugin_internal_proto_depIdxs = nil
 }
diff --git a/api/go/gosdn/plugin-internal/plugin-internal.pb.gw.go b/api/go/gosdn/plugin-internal/plugin-internal.pb.gw.go
new file mode 100644
index 000000000..9fd179fdf
--- /dev/null
+++ b/api/go/gosdn/plugin-internal/plugin-internal.pb.gw.go
@@ -0,0 +1,162 @@
+// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
+// source: gosdn/plugin-internal/plugin-internal.proto
+
+/*
+Package plugin_internal is a reverse proxy.
+
+It translates gRPC into RESTful JSON APIs.
+*/
+package plugin_internal
+
+import (
+	"context"
+	"errors"
+	"io"
+	"net/http"
+
+	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
+	"github.com/grpc-ecosystem/grpc-gateway/v2/utilities"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/grpclog"
+	"google.golang.org/grpc/metadata"
+	"google.golang.org/grpc/status"
+	"google.golang.org/protobuf/proto"
+)
+
+// Suppress "imported and not used" errors
+var (
+	_ codes.Code
+	_ io.Reader
+	_ status.Status
+	_ = errors.New
+	_ = runtime.String
+	_ = utilities.NewDoubleArray
+	_ = metadata.Join
+)
+
+var filter_PluginInternalService_GetAvailablePlugins_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
+
+func request_PluginInternalService_GetAvailablePlugins_0(ctx context.Context, marshaler runtime.Marshaler, client PluginInternalServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+	var (
+		protoReq GetAvailablePluginsRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := req.ParseForm(); err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_PluginInternalService_GetAvailablePlugins_0); err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	msg, err := client.GetAvailablePlugins(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+	return msg, metadata, err
+}
+
+func local_request_PluginInternalService_GetAvailablePlugins_0(ctx context.Context, marshaler runtime.Marshaler, server PluginInternalServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+	var (
+		protoReq GetAvailablePluginsRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := req.ParseForm(); err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_PluginInternalService_GetAvailablePlugins_0); err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	msg, err := server.GetAvailablePlugins(ctx, &protoReq)
+	return msg, metadata, err
+}
+
+// RegisterPluginInternalServiceHandlerServer registers the http handlers for service PluginInternalService to "mux".
+// UnaryRPC     :call PluginInternalServiceServer directly.
+// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
+// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterPluginInternalServiceHandlerFromEndpoint instead.
+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
+func RegisterPluginInternalServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server PluginInternalServiceServer) error {
+	mux.Handle(http.MethodGet, pattern_PluginInternalService_GetAvailablePlugins_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+		ctx, cancel := context.WithCancel(req.Context())
+		defer cancel()
+		var stream runtime.ServerTransportStream
+		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.plugin_internal.PluginInternalService/GetAvailablePlugins", runtime.WithHTTPPathPattern("/plugins"))
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+		resp, md, err := local_request_PluginInternalService_GetAvailablePlugins_0(annotatedContext, inboundMarshaler, server, req, pathParams)
+		md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+		annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
+		if err != nil {
+			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
+			return
+		}
+		forward_PluginInternalService_GetAvailablePlugins_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+	})
+
+	return nil
+}
+
+// RegisterPluginInternalServiceHandlerFromEndpoint is same as RegisterPluginInternalServiceHandler but
+// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
+func RegisterPluginInternalServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
+	conn, err := grpc.NewClient(endpoint, opts...)
+	if err != nil {
+		return err
+	}
+	defer func() {
+		if err != nil {
+			if cerr := conn.Close(); cerr != nil {
+				grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
+			}
+			return
+		}
+		go func() {
+			<-ctx.Done()
+			if cerr := conn.Close(); cerr != nil {
+				grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
+			}
+		}()
+	}()
+	return RegisterPluginInternalServiceHandler(ctx, mux, conn)
+}
+
+// RegisterPluginInternalServiceHandler registers the http handlers for service PluginInternalService to "mux".
+// The handlers forward requests to the grpc endpoint over "conn".
+func RegisterPluginInternalServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
+	return RegisterPluginInternalServiceHandlerClient(ctx, mux, NewPluginInternalServiceClient(conn))
+}
+
+// RegisterPluginInternalServiceHandlerClient registers the http handlers for service PluginInternalService
+// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "PluginInternalServiceClient".
+// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "PluginInternalServiceClient"
+// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
+// "PluginInternalServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares.
+func RegisterPluginInternalServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client PluginInternalServiceClient) error {
+	mux.Handle(http.MethodGet, pattern_PluginInternalService_GetAvailablePlugins_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+		ctx, cancel := context.WithCancel(req.Context())
+		defer cancel()
+		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.plugin_internal.PluginInternalService/GetAvailablePlugins", runtime.WithHTTPPathPattern("/plugins"))
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+		resp, md, err := request_PluginInternalService_GetAvailablePlugins_0(annotatedContext, inboundMarshaler, client, req, pathParams)
+		annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
+		if err != nil {
+			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
+			return
+		}
+		forward_PluginInternalService_GetAvailablePlugins_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+	})
+	return nil
+}
+
+var (
+	pattern_PluginInternalService_GetAvailablePlugins_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"plugins"}, ""))
+)
+
+var (
+	forward_PluginInternalService_GetAvailablePlugins_0 = runtime.ForwardResponseMessage
+)
diff --git a/api/go/gosdn/plugin-internal/plugin-internal_grpc.pb.go b/api/go/gosdn/plugin-internal/plugin-internal_grpc.pb.go
index eaa452aa3..31b9539de 100755
--- a/api/go/gosdn/plugin-internal/plugin-internal_grpc.pb.go
+++ b/api/go/gosdn/plugin-internal/plugin-internal_grpc.pb.go
@@ -20,8 +20,9 @@ import (
 const _ = grpc.SupportPackageIsVersion9
 
 const (
-	PluginInternalService_AvailablePlugins_FullMethodName = "/gosdn.plugin_internal.PluginInternalService/AvailablePlugins"
-	PluginInternalService_GetPluginSchema_FullMethodName  = "/gosdn.plugin_internal.PluginInternalService/GetPluginSchema"
+	PluginInternalService_AvailablePlugins_FullMethodName    = "/gosdn.plugin_internal.PluginInternalService/AvailablePlugins"
+	PluginInternalService_GetPluginSchema_FullMethodName     = "/gosdn.plugin_internal.PluginInternalService/GetPluginSchema"
+	PluginInternalService_GetAvailablePlugins_FullMethodName = "/gosdn.plugin_internal.PluginInternalService/GetAvailablePlugins"
 )
 
 // PluginInternalServiceClient is the client API for PluginInternalService service.
@@ -30,6 +31,7 @@ const (
 type PluginInternalServiceClient interface {
 	AvailablePlugins(ctx context.Context, in *GetAvailablePluginsRequest, opts ...grpc.CallOption) (*plugin_registry.GetResponse, error)
 	GetPluginSchema(ctx context.Context, in *GetPluginSchemaRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[PluginSchemaPayload], error)
+	GetAvailablePlugins(ctx context.Context, in *GetAvailablePluginsRequest, opts ...grpc.CallOption) (*plugin_registry.GetResponse, error)
 }
 
 type pluginInternalServiceClient struct {
@@ -69,12 +71,23 @@ func (c *pluginInternalServiceClient) GetPluginSchema(ctx context.Context, in *G
 // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
 type PluginInternalService_GetPluginSchemaClient = grpc.ServerStreamingClient[PluginSchemaPayload]
 
+func (c *pluginInternalServiceClient) GetAvailablePlugins(ctx context.Context, in *GetAvailablePluginsRequest, opts ...grpc.CallOption) (*plugin_registry.GetResponse, error) {
+	cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+	out := new(plugin_registry.GetResponse)
+	err := c.cc.Invoke(ctx, PluginInternalService_GetAvailablePlugins_FullMethodName, in, out, cOpts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
 // PluginInternalServiceServer is the server API for PluginInternalService service.
 // All implementations must embed UnimplementedPluginInternalServiceServer
 // for forward compatibility.
 type PluginInternalServiceServer interface {
 	AvailablePlugins(context.Context, *GetAvailablePluginsRequest) (*plugin_registry.GetResponse, error)
 	GetPluginSchema(*GetPluginSchemaRequest, grpc.ServerStreamingServer[PluginSchemaPayload]) error
+	GetAvailablePlugins(context.Context, *GetAvailablePluginsRequest) (*plugin_registry.GetResponse, error)
 	mustEmbedUnimplementedPluginInternalServiceServer()
 }
 
@@ -91,6 +104,9 @@ func (UnimplementedPluginInternalServiceServer) AvailablePlugins(context.Context
 func (UnimplementedPluginInternalServiceServer) GetPluginSchema(*GetPluginSchemaRequest, grpc.ServerStreamingServer[PluginSchemaPayload]) error {
 	return status.Errorf(codes.Unimplemented, "method GetPluginSchema not implemented")
 }
+func (UnimplementedPluginInternalServiceServer) GetAvailablePlugins(context.Context, *GetAvailablePluginsRequest) (*plugin_registry.GetResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method GetAvailablePlugins not implemented")
+}
 func (UnimplementedPluginInternalServiceServer) mustEmbedUnimplementedPluginInternalServiceServer() {}
 func (UnimplementedPluginInternalServiceServer) testEmbeddedByValue()                               {}
 
@@ -141,6 +157,24 @@ func _PluginInternalService_GetPluginSchema_Handler(srv interface{}, stream grpc
 // This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
 type PluginInternalService_GetPluginSchemaServer = grpc.ServerStreamingServer[PluginSchemaPayload]
 
+func _PluginInternalService_GetAvailablePlugins_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(GetAvailablePluginsRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(PluginInternalServiceServer).GetAvailablePlugins(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: PluginInternalService_GetAvailablePlugins_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(PluginInternalServiceServer).GetAvailablePlugins(ctx, req.(*GetAvailablePluginsRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
 // PluginInternalService_ServiceDesc is the grpc.ServiceDesc for PluginInternalService service.
 // It's only intended for direct use with grpc.RegisterService,
 // and not to be introspected or modified (even as a copy)
@@ -152,6 +186,10 @@ var PluginInternalService_ServiceDesc = grpc.ServiceDesc{
 			MethodName: "AvailablePlugins",
 			Handler:    _PluginInternalService_AvailablePlugins_Handler,
 		},
+		{
+			MethodName: "GetAvailablePlugins",
+			Handler:    _PluginInternalService_GetAvailablePlugins_Handler,
+		},
 	},
 	Streams: []grpc.StreamDesc{
 		{
diff --git a/api/go/gosdn/plugin-registry/plugin-registry.pb.go b/api/go/gosdn/plugin-registry/plugin-registry.pb.go
index 7bb50e04f..ed6853721 100755
--- a/api/go/gosdn/plugin-registry/plugin-registry.pb.go
+++ b/api/go/gosdn/plugin-registry/plugin-registry.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: gosdn/plugin-registry/plugin-registry.proto
 
@@ -8,11 +8,13 @@ package plugin_registry
 
 import (
 	_ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate"
+	_ "google.golang.org/genproto/googleapis/api/annotations"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 	_ "google.golang.org/protobuf/types/known/timestamppb"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -23,12 +25,11 @@ const (
 )
 
 type GetRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Query         []*Query               `protobuf:"bytes,2,rep,name=query,proto3" json:"query,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64    `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Query     []*Query `protobuf:"bytes,2,rep,name=query,proto3" json:"query,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetRequest) Reset() {
@@ -76,11 +77,10 @@ func (x *GetRequest) GetQuery() []*Query {
 }
 
 type GetAllRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetAllRequest) Reset() {
@@ -121,15 +121,14 @@ func (x *GetAllRequest) GetTimestamp() int64 {
 }
 
 type Query struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Types that are assignable to Identifier:
+	state protoimpl.MessageState `protogen:"open.v1"`
+	// Types that are valid to be assigned to Identifier:
 	//
 	//	*Query_Id
 	//	*Query_Name
-	Identifier isQuery_Identifier `protobuf_oneof:"identifier"`
+	Identifier    isQuery_Identifier `protobuf_oneof:"identifier"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Query) Reset() {
@@ -162,23 +161,27 @@ func (*Query) Descriptor() ([]byte, []int) {
 	return file_gosdn_plugin_registry_plugin_registry_proto_rawDescGZIP(), []int{2}
 }
 
-func (m *Query) GetIdentifier() isQuery_Identifier {
-	if m != nil {
-		return m.Identifier
+func (x *Query) GetIdentifier() isQuery_Identifier {
+	if x != nil {
+		return x.Identifier
 	}
 	return nil
 }
 
 func (x *Query) GetId() string {
-	if x, ok := x.GetIdentifier().(*Query_Id); ok {
-		return x.Id
+	if x != nil {
+		if x, ok := x.Identifier.(*Query_Id); ok {
+			return x.Id
+		}
 	}
 	return ""
 }
 
 func (x *Query) GetName() string {
-	if x, ok := x.GetIdentifier().(*Query_Name); ok {
-		return x.Name
+	if x != nil {
+		if x, ok := x.Identifier.(*Query_Name); ok {
+			return x.Name
+		}
 	}
 	return ""
 }
@@ -200,12 +203,11 @@ func (*Query_Id) isQuery_Identifier() {}
 func (*Query_Name) isQuery_Identifier() {}
 
 type GetResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Plugins       []*Plugin              `protobuf:"bytes,2,rep,name=plugins,proto3" json:"plugins,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64     `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Plugins   []*Plugin `protobuf:"bytes,2,rep,name=plugins,proto3" json:"plugins,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetResponse) Reset() {
@@ -253,12 +255,11 @@ func (x *GetResponse) GetPlugins() []*Plugin {
 }
 
 type GetDownloadRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Id            string                 `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Id        string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetDownloadRequest) Reset() {
@@ -306,11 +307,10 @@ func (x *GetDownloadRequest) GetId() string {
 }
 
 type GetDownloadPayload struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Chunk         []byte                 `protobuf:"bytes,1,opt,name=chunk,proto3" json:"chunk,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Chunk []byte `protobuf:"bytes,1,opt,name=chunk,proto3" json:"chunk,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetDownloadPayload) Reset() {
@@ -351,12 +351,11 @@ func (x *GetDownloadPayload) GetChunk() []byte {
 }
 
 type DeleteRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Id            []string               `protobuf:"bytes,2,rep,name=id,proto3" json:"id,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64    `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Id        []string `protobuf:"bytes,2,rep,name=id,proto3" json:"id,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeleteRequest) Reset() {
@@ -404,11 +403,10 @@ func (x *DeleteRequest) GetId() []string {
 }
 
 type DeleteResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeleteResponse) Reset() {
@@ -449,12 +447,11 @@ func (x *DeleteResponse) GetTimestamp() int64 {
 }
 
 type Plugin struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Id            string                 `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	Manifest      *Manifest              `protobuf:"bytes,2,opt,name=manifest,proto3" json:"manifest,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Id       string    `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	Manifest *Manifest `protobuf:"bytes,2,opt,name=manifest,proto3" json:"manifest,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Plugin) Reset() {
@@ -502,14 +499,13 @@ func (x *Plugin) GetManifest() *Manifest {
 }
 
 type Manifest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Name          string                 `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+	Firmware      string                 `protobuf:"bytes,2,opt,name=firmware,proto3" json:"firmware,omitempty"`
+	Author        string                 `protobuf:"bytes,3,opt,name=author,proto3" json:"author,omitempty"`
+	Version       string                 `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Name     string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
-	Firmware string `protobuf:"bytes,2,opt,name=firmware,proto3" json:"firmware,omitempty"`
-	Author   string `protobuf:"bytes,3,opt,name=author,proto3" json:"author,omitempty"`
-	Version  string `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Manifest) Reset() {
@@ -570,9 +566,105 @@ func (x *Manifest) GetVersion() string {
 	return ""
 }
 
+type GetAvailablePluginsResponse struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Plugins       []*Plugin              `protobuf:"bytes,2,rep,name=plugins,proto3" json:"plugins,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *GetAvailablePluginsResponse) Reset() {
+	*x = GetAvailablePluginsResponse{}
+	mi := &file_gosdn_plugin_registry_plugin_registry_proto_msgTypes[10]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *GetAvailablePluginsResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetAvailablePluginsResponse) ProtoMessage() {}
+
+func (x *GetAvailablePluginsResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_gosdn_plugin_registry_plugin_registry_proto_msgTypes[10]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use GetAvailablePluginsResponse.ProtoReflect.Descriptor instead.
+func (*GetAvailablePluginsResponse) Descriptor() ([]byte, []int) {
+	return file_gosdn_plugin_registry_plugin_registry_proto_rawDescGZIP(), []int{10}
+}
+
+func (x *GetAvailablePluginsResponse) GetTimestamp() int64 {
+	if x != nil {
+		return x.Timestamp
+	}
+	return 0
+}
+
+func (x *GetAvailablePluginsResponse) GetPlugins() []*Plugin {
+	if x != nil {
+		return x.Plugins
+	}
+	return nil
+}
+
+type GetAvailablePluginsRequest struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *GetAvailablePluginsRequest) Reset() {
+	*x = GetAvailablePluginsRequest{}
+	mi := &file_gosdn_plugin_registry_plugin_registry_proto_msgTypes[11]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *GetAvailablePluginsRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetAvailablePluginsRequest) ProtoMessage() {}
+
+func (x *GetAvailablePluginsRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_gosdn_plugin_registry_plugin_registry_proto_msgTypes[11]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use GetAvailablePluginsRequest.ProtoReflect.Descriptor instead.
+func (*GetAvailablePluginsRequest) Descriptor() ([]byte, []int) {
+	return file_gosdn_plugin_registry_plugin_registry_proto_rawDescGZIP(), []int{11}
+}
+
+func (x *GetAvailablePluginsRequest) GetTimestamp() int64 {
+	if x != nil {
+		return x.Timestamp
+	}
+	return 0
+}
+
 var File_gosdn_plugin_registry_plugin_registry_proto protoreflect.FileDescriptor
 
-var file_gosdn_plugin_registry_plugin_registry_proto_rawDesc = []byte{
+var file_gosdn_plugin_registry_plugin_registry_proto_rawDesc = string([]byte{
 	0x0a, 0x2b, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2d, 0x72,
 	0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2d, 0x72,
 	0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x67,
@@ -581,55 +673,68 @@ var file_gosdn_plugin_registry_plugin_registry_proto_rawDesc = []byte{
 	0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e,
 	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x62, 0x75, 0x66, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64,
 	0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x22, 0x66, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3a,
-	0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e,
-	0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x67,
-	0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x42, 0x06, 0xba, 0x48, 0x03,
-	0xc8, 0x01, 0x01, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x22, 0x2d, 0x0a, 0x0d, 0x47, 0x65,
-	0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74,
-	0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09,
-	0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x4d, 0x0a, 0x05, 0x51, 0x75, 0x65,
-	0x72, 0x79, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06,
-	0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x48, 0x00, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x04,
-	0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8,
-	0x01, 0x01, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x0c, 0x0a, 0x0a, 0x69, 0x64,
-	0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x22, 0x64, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x52,
-	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73,
-	0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65,
-	0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x37, 0x0a, 0x07, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73,
-	0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70,
-	0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x50,
-	0x6c, 0x75, 0x67, 0x69, 0x6e, 0x52, 0x07, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x22, 0x4a,
-	0x0a, 0x12, 0x47, 0x65, 0x74, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71,
+	0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61,
+	0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x22, 0x66, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c,
+	0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3a, 0x0a, 0x05,
+	0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f,
+	0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73,
+	0x74, 0x72, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01,
+	0x01, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x22, 0x2d, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x41,
+	0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d,
+	0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69,
+	0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x4d, 0x0a, 0x05, 0x51, 0x75, 0x65, 0x72, 0x79,
+	0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48,
+	0x03, 0xc8, 0x01, 0x01, 0x48, 0x00, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x04, 0x6e, 0x61,
+	0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01,
+	0x48, 0x00, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x0c, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e,
+	0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x22, 0x64, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73,
+	0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
+	0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74,
+	0x61, 0x6d, 0x70, 0x12, 0x37, 0x0a, 0x07, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x18, 0x02,
+	0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75,
+	0x67, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x50, 0x6c, 0x75,
+	0x67, 0x69, 0x6e, 0x52, 0x07, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x22, 0x4a, 0x0a, 0x12,
+	0x47, 0x65, 0x74, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
+	0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48,
+	0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x2a, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x44,
+	0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x14,
+	0x0a, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63,
+	0x68, 0x75, 0x6e, 0x6b, 0x22, 0x45, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
+	0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74,
+	0x61, 0x6d, 0x70, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x42,
+	0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x2e, 0x0a, 0x0e, 0x44,
+	0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a,
+	0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03,
+	0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x55, 0x0a, 0x06, 0x50,
+	0x6c, 0x75, 0x67, 0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x3b, 0x0a, 0x08, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73,
+	0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e,
+	0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e,
+	0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x52, 0x08, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65,
+	0x73, 0x74, 0x22, 0x6c, 0x0a, 0x08, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x12, 0x12,
+	0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
+	0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65, 0x12, 0x16,
+	0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
+	0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
+	0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+	0x22, 0x74, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65,
+	0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
+	0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x37, 0x0a,
+	0x07, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d,
+	0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x72, 0x65,
+	0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x52, 0x07, 0x70,
+	0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x22, 0x3a, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x41, 0x76, 0x61,
+	0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71,
 	0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
 	0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
-	0x6d, 0x70, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06,
-	0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x2a, 0x0a, 0x12, 0x47, 0x65,
-	0x74, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64,
-	0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52,
-	0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x22, 0x45, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73,
-	0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65,
-	0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x16, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28,
-	0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x2e, 0x0a,
-	0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
-	0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x55, 0x0a,
-	0x06, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x3b, 0x0a, 0x08, 0x6d, 0x61, 0x6e, 0x69, 0x66,
-	0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x73, 0x64,
-	0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72,
-	0x79, 0x2e, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x52, 0x08, 0x6d, 0x61, 0x6e, 0x69,
-	0x66, 0x65, 0x73, 0x74, 0x22, 0x6c, 0x0a, 0x08, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74,
-	0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
-	0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65,
-	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x72, 0x6d, 0x77, 0x61, 0x72, 0x65,
-	0x12, 0x16, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73,
-	0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69,
-	0x6f, 0x6e, 0x32, 0xf4, 0x02, 0x0a, 0x15, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x67,
+	0x6d, 0x70, 0x32, 0xf4, 0x02, 0x0a, 0x15, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x67,
 	0x69, 0x73, 0x74, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x03,
 	0x47, 0x65, 0x74, 0x12, 0x21, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67,
 	0x69, 0x6e, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x52,
@@ -657,50 +762,53 @@ var file_gosdn_plugin_registry_plugin_registry_proto_rawDesc = []byte{
 	0x6e, 0x65, 0x74, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f,
 	0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2d, 0x72, 0x65,
 	0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_gosdn_plugin_registry_plugin_registry_proto_rawDescOnce sync.Once
-	file_gosdn_plugin_registry_plugin_registry_proto_rawDescData = file_gosdn_plugin_registry_plugin_registry_proto_rawDesc
+	file_gosdn_plugin_registry_plugin_registry_proto_rawDescData []byte
 )
 
 func file_gosdn_plugin_registry_plugin_registry_proto_rawDescGZIP() []byte {
 	file_gosdn_plugin_registry_plugin_registry_proto_rawDescOnce.Do(func() {
-		file_gosdn_plugin_registry_plugin_registry_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdn_plugin_registry_plugin_registry_proto_rawDescData)
+		file_gosdn_plugin_registry_plugin_registry_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gosdn_plugin_registry_plugin_registry_proto_rawDesc), len(file_gosdn_plugin_registry_plugin_registry_proto_rawDesc)))
 	})
 	return file_gosdn_plugin_registry_plugin_registry_proto_rawDescData
 }
 
-var file_gosdn_plugin_registry_plugin_registry_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
+var file_gosdn_plugin_registry_plugin_registry_proto_msgTypes = make([]protoimpl.MessageInfo, 12)
 var file_gosdn_plugin_registry_plugin_registry_proto_goTypes = []any{
-	(*GetRequest)(nil),         // 0: gosdn.plugin_registry.GetRequest
-	(*GetAllRequest)(nil),      // 1: gosdn.plugin_registry.GetAllRequest
-	(*Query)(nil),              // 2: gosdn.plugin_registry.Query
-	(*GetResponse)(nil),        // 3: gosdn.plugin_registry.GetResponse
-	(*GetDownloadRequest)(nil), // 4: gosdn.plugin_registry.GetDownloadRequest
-	(*GetDownloadPayload)(nil), // 5: gosdn.plugin_registry.GetDownloadPayload
-	(*DeleteRequest)(nil),      // 6: gosdn.plugin_registry.DeleteRequest
-	(*DeleteResponse)(nil),     // 7: gosdn.plugin_registry.DeleteResponse
-	(*Plugin)(nil),             // 8: gosdn.plugin_registry.Plugin
-	(*Manifest)(nil),           // 9: gosdn.plugin_registry.Manifest
+	(*GetRequest)(nil),                  // 0: gosdn.plugin_registry.GetRequest
+	(*GetAllRequest)(nil),               // 1: gosdn.plugin_registry.GetAllRequest
+	(*Query)(nil),                       // 2: gosdn.plugin_registry.Query
+	(*GetResponse)(nil),                 // 3: gosdn.plugin_registry.GetResponse
+	(*GetDownloadRequest)(nil),          // 4: gosdn.plugin_registry.GetDownloadRequest
+	(*GetDownloadPayload)(nil),          // 5: gosdn.plugin_registry.GetDownloadPayload
+	(*DeleteRequest)(nil),               // 6: gosdn.plugin_registry.DeleteRequest
+	(*DeleteResponse)(nil),              // 7: gosdn.plugin_registry.DeleteResponse
+	(*Plugin)(nil),                      // 8: gosdn.plugin_registry.Plugin
+	(*Manifest)(nil),                    // 9: gosdn.plugin_registry.Manifest
+	(*GetAvailablePluginsResponse)(nil), // 10: gosdn.plugin_registry.GetAvailablePluginsResponse
+	(*GetAvailablePluginsRequest)(nil),  // 11: gosdn.plugin_registry.GetAvailablePluginsRequest
 }
 var file_gosdn_plugin_registry_plugin_registry_proto_depIdxs = []int32{
 	2, // 0: gosdn.plugin_registry.GetRequest.query:type_name -> gosdn.plugin_registry.Query
 	8, // 1: gosdn.plugin_registry.GetResponse.plugins:type_name -> gosdn.plugin_registry.Plugin
 	9, // 2: gosdn.plugin_registry.Plugin.manifest:type_name -> gosdn.plugin_registry.Manifest
-	0, // 3: gosdn.plugin_registry.PluginRegistryService.Get:input_type -> gosdn.plugin_registry.GetRequest
-	1, // 4: gosdn.plugin_registry.PluginRegistryService.GetAll:input_type -> gosdn.plugin_registry.GetAllRequest
-	4, // 5: gosdn.plugin_registry.PluginRegistryService.Download:input_type -> gosdn.plugin_registry.GetDownloadRequest
-	6, // 6: gosdn.plugin_registry.PluginRegistryService.Delete:input_type -> gosdn.plugin_registry.DeleteRequest
-	3, // 7: gosdn.plugin_registry.PluginRegistryService.Get:output_type -> gosdn.plugin_registry.GetResponse
-	3, // 8: gosdn.plugin_registry.PluginRegistryService.GetAll:output_type -> gosdn.plugin_registry.GetResponse
-	5, // 9: gosdn.plugin_registry.PluginRegistryService.Download:output_type -> gosdn.plugin_registry.GetDownloadPayload
-	7, // 10: gosdn.plugin_registry.PluginRegistryService.Delete:output_type -> gosdn.plugin_registry.DeleteResponse
-	7, // [7:11] is the sub-list for method output_type
-	3, // [3:7] is the sub-list for method input_type
-	3, // [3:3] is the sub-list for extension type_name
-	3, // [3:3] is the sub-list for extension extendee
-	0, // [0:3] is the sub-list for field type_name
+	8, // 3: gosdn.plugin_registry.GetAvailablePluginsResponse.plugins:type_name -> gosdn.plugin_registry.Plugin
+	0, // 4: gosdn.plugin_registry.PluginRegistryService.Get:input_type -> gosdn.plugin_registry.GetRequest
+	1, // 5: gosdn.plugin_registry.PluginRegistryService.GetAll:input_type -> gosdn.plugin_registry.GetAllRequest
+	4, // 6: gosdn.plugin_registry.PluginRegistryService.Download:input_type -> gosdn.plugin_registry.GetDownloadRequest
+	6, // 7: gosdn.plugin_registry.PluginRegistryService.Delete:input_type -> gosdn.plugin_registry.DeleteRequest
+	3, // 8: gosdn.plugin_registry.PluginRegistryService.Get:output_type -> gosdn.plugin_registry.GetResponse
+	3, // 9: gosdn.plugin_registry.PluginRegistryService.GetAll:output_type -> gosdn.plugin_registry.GetResponse
+	5, // 10: gosdn.plugin_registry.PluginRegistryService.Download:output_type -> gosdn.plugin_registry.GetDownloadPayload
+	7, // 11: gosdn.plugin_registry.PluginRegistryService.Delete:output_type -> gosdn.plugin_registry.DeleteResponse
+	8, // [8:12] is the sub-list for method output_type
+	4, // [4:8] is the sub-list for method input_type
+	4, // [4:4] is the sub-list for extension type_name
+	4, // [4:4] is the sub-list for extension extendee
+	0, // [0:4] is the sub-list for field type_name
 }
 
 func init() { file_gosdn_plugin_registry_plugin_registry_proto_init() }
@@ -716,9 +824,9 @@ func file_gosdn_plugin_registry_plugin_registry_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdn_plugin_registry_plugin_registry_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_gosdn_plugin_registry_plugin_registry_proto_rawDesc), len(file_gosdn_plugin_registry_plugin_registry_proto_rawDesc)),
 			NumEnums:      0,
-			NumMessages:   10,
+			NumMessages:   12,
 			NumExtensions: 0,
 			NumServices:   1,
 		},
@@ -727,7 +835,6 @@ func file_gosdn_plugin_registry_plugin_registry_proto_init() {
 		MessageInfos:      file_gosdn_plugin_registry_plugin_registry_proto_msgTypes,
 	}.Build()
 	File_gosdn_plugin_registry_plugin_registry_proto = out.File
-	file_gosdn_plugin_registry_plugin_registry_proto_rawDesc = nil
 	file_gosdn_plugin_registry_plugin_registry_proto_goTypes = nil
 	file_gosdn_plugin_registry_plugin_registry_proto_depIdxs = nil
 }
diff --git a/api/go/gosdn/plugin-registry/plugin-registry.pb.gw.go b/api/go/gosdn/plugin-registry/plugin-registry.pb.gw.go
new file mode 100644
index 000000000..bd500348f
--- /dev/null
+++ b/api/go/gosdn/plugin-registry/plugin-registry.pb.gw.go
@@ -0,0 +1,162 @@
+// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
+// source: gosdn/plugin-registry/plugin-registry.proto
+
+/*
+Package plugin_registry is a reverse proxy.
+
+It translates gRPC into RESTful JSON APIs.
+*/
+package plugin_registry
+
+import (
+	"context"
+	"errors"
+	"io"
+	"net/http"
+
+	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
+	"github.com/grpc-ecosystem/grpc-gateway/v2/utilities"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/grpclog"
+	"google.golang.org/grpc/metadata"
+	"google.golang.org/grpc/status"
+	"google.golang.org/protobuf/proto"
+)
+
+// Suppress "imported and not used" errors
+var (
+	_ codes.Code
+	_ io.Reader
+	_ status.Status
+	_ = errors.New
+	_ = runtime.String
+	_ = utilities.NewDoubleArray
+	_ = metadata.Join
+)
+
+var filter_PluginRegistryService_GetAll_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
+
+func request_PluginRegistryService_GetAll_0(ctx context.Context, marshaler runtime.Marshaler, client PluginRegistryServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+	var (
+		protoReq GetAllRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := req.ParseForm(); err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_PluginRegistryService_GetAll_0); err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	msg, err := client.GetAll(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+	return msg, metadata, err
+}
+
+func local_request_PluginRegistryService_GetAll_0(ctx context.Context, marshaler runtime.Marshaler, server PluginRegistryServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+	var (
+		protoReq GetAllRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := req.ParseForm(); err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_PluginRegistryService_GetAll_0); err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	msg, err := server.GetAll(ctx, &protoReq)
+	return msg, metadata, err
+}
+
+// RegisterPluginRegistryServiceHandlerServer registers the http handlers for service PluginRegistryService to "mux".
+// UnaryRPC     :call PluginRegistryServiceServer directly.
+// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
+// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterPluginRegistryServiceHandlerFromEndpoint instead.
+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
+func RegisterPluginRegistryServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server PluginRegistryServiceServer) error {
+	mux.Handle(http.MethodGet, pattern_PluginRegistryService_GetAll_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+		ctx, cancel := context.WithCancel(req.Context())
+		defer cancel()
+		var stream runtime.ServerTransportStream
+		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.plugin_registry.PluginRegistryService/GetAll", runtime.WithHTTPPathPattern("/plugins/here"))
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+		resp, md, err := local_request_PluginRegistryService_GetAll_0(annotatedContext, inboundMarshaler, server, req, pathParams)
+		md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+		annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
+		if err != nil {
+			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
+			return
+		}
+		forward_PluginRegistryService_GetAll_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+	})
+
+	return nil
+}
+
+// RegisterPluginRegistryServiceHandlerFromEndpoint is same as RegisterPluginRegistryServiceHandler but
+// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
+func RegisterPluginRegistryServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
+	conn, err := grpc.NewClient(endpoint, opts...)
+	if err != nil {
+		return err
+	}
+	defer func() {
+		if err != nil {
+			if cerr := conn.Close(); cerr != nil {
+				grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
+			}
+			return
+		}
+		go func() {
+			<-ctx.Done()
+			if cerr := conn.Close(); cerr != nil {
+				grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
+			}
+		}()
+	}()
+	return RegisterPluginRegistryServiceHandler(ctx, mux, conn)
+}
+
+// RegisterPluginRegistryServiceHandler registers the http handlers for service PluginRegistryService to "mux".
+// The handlers forward requests to the grpc endpoint over "conn".
+func RegisterPluginRegistryServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
+	return RegisterPluginRegistryServiceHandlerClient(ctx, mux, NewPluginRegistryServiceClient(conn))
+}
+
+// RegisterPluginRegistryServiceHandlerClient registers the http handlers for service PluginRegistryService
+// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "PluginRegistryServiceClient".
+// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "PluginRegistryServiceClient"
+// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
+// "PluginRegistryServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares.
+func RegisterPluginRegistryServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client PluginRegistryServiceClient) error {
+	mux.Handle(http.MethodGet, pattern_PluginRegistryService_GetAll_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+		ctx, cancel := context.WithCancel(req.Context())
+		defer cancel()
+		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.plugin_registry.PluginRegistryService/GetAll", runtime.WithHTTPPathPattern("/plugins/here"))
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+		resp, md, err := request_PluginRegistryService_GetAll_0(annotatedContext, inboundMarshaler, client, req, pathParams)
+		annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
+		if err != nil {
+			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
+			return
+		}
+		forward_PluginRegistryService_GetAll_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+	})
+	return nil
+}
+
+var (
+	pattern_PluginRegistryService_GetAll_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"plugins", "here"}, ""))
+)
+
+var (
+	forward_PluginRegistryService_GetAll_0 = runtime.ForwardResponseMessage
+)
diff --git a/api/go/gosdn/plugin/plugin.pb.go b/api/go/gosdn/plugin/plugin.pb.go
index 9193b62ac..273425267 100755
--- a/api/go/gosdn/plugin/plugin.pb.go
+++ b/api/go/gosdn/plugin/plugin.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: gosdn/plugin/plugin.proto
 
@@ -9,11 +9,14 @@ package plugin
 import (
 	_ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate"
 	networkelement "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/networkelement"
+	plugin_registry "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/plugin-registry"
 	gnmi "github.com/openconfig/gnmi/proto/gnmi"
+	_ "google.golang.org/genproto/googleapis/api/annotations"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -24,13 +27,12 @@ const (
 )
 
 type UnmarshalRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Json          []byte                 `protobuf:"bytes,1,opt,name=json,proto3" json:"json,omitempty"`
+	Path          *gnmi.Path             `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
+	Value         *gnmi.TypedValue       `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Json  []byte           `protobuf:"bytes,1,opt,name=json,proto3" json:"json,omitempty"`
-	Path  *gnmi.Path       `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
-	Value *gnmi.TypedValue `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *UnmarshalRequest) Reset() {
@@ -85,11 +87,10 @@ func (x *UnmarshalRequest) GetValue() *gnmi.TypedValue {
 }
 
 type UnmarshalResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Valid         bool                   `protobuf:"varint,1,opt,name=valid,proto3" json:"valid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Valid bool `protobuf:"varint,1,opt,name=valid,proto3" json:"valid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *UnmarshalResponse) Reset() {
@@ -130,12 +131,11 @@ func (x *UnmarshalResponse) GetValid() bool {
 }
 
 type SetNodeRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Path          *gnmi.Path             `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
+	Value         *gnmi.TypedValue       `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Path  *gnmi.Path       `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
-	Value *gnmi.TypedValue `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *SetNodeRequest) Reset() {
@@ -183,11 +183,10 @@ func (x *SetNodeRequest) GetValue() *gnmi.TypedValue {
 }
 
 type SetNodeResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Valid         bool                   `protobuf:"varint,1,opt,name=valid,proto3" json:"valid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Valid bool `protobuf:"varint,1,opt,name=valid,proto3" json:"valid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *SetNodeResponse) Reset() {
@@ -228,12 +227,11 @@ func (x *SetNodeResponse) GetValid() bool {
 }
 
 type GetNodeRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Path                    *gnmi.Path `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
-	RequestForIntendedState bool       `protobuf:"varint,3,opt,name=requestForIntendedState,proto3" json:"requestForIntendedState,omitempty"`
+	state                   protoimpl.MessageState `protogen:"open.v1"`
+	Path                    *gnmi.Path             `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
+	RequestForIntendedState bool                   `protobuf:"varint,3,opt,name=requestForIntendedState,proto3" json:"requestForIntendedState,omitempty"`
+	unknownFields           protoimpl.UnknownFields
+	sizeCache               protoimpl.SizeCache
 }
 
 func (x *GetNodeRequest) Reset() {
@@ -281,11 +279,10 @@ func (x *GetNodeRequest) GetRequestForIntendedState() bool {
 }
 
 type GetNodeResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Nodes         []*gnmi.Notification   `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Nodes []*gnmi.Notification `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetNodeResponse) Reset() {
@@ -326,11 +323,10 @@ func (x *GetNodeResponse) GetNodes() []*gnmi.Notification {
 }
 
 type DeleteNodeRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Path          *gnmi.Path             `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Path *gnmi.Path `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeleteNodeRequest) Reset() {
@@ -371,11 +367,10 @@ func (x *DeleteNodeRequest) GetPath() *gnmi.Path {
 }
 
 type DeleteNodeResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Valid         bool                   `protobuf:"varint,1,opt,name=valid,proto3" json:"valid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Valid bool `protobuf:"varint,1,opt,name=valid,proto3" json:"valid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeleteNodeResponse) Reset() {
@@ -416,11 +411,10 @@ func (x *DeleteNodeResponse) GetValid() bool {
 }
 
 type ModelRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	FilterReadOnly bool `protobuf:"varint,1,opt,name=filterReadOnly,proto3" json:"filterReadOnly,omitempty"`
+	state          protoimpl.MessageState `protogen:"open.v1"`
+	FilterReadOnly bool                   `protobuf:"varint,1,opt,name=filterReadOnly,proto3" json:"filterReadOnly,omitempty"`
+	unknownFields  protoimpl.UnknownFields
+	sizeCache      protoimpl.SizeCache
 }
 
 func (x *ModelRequest) Reset() {
@@ -461,11 +455,10 @@ func (x *ModelRequest) GetFilterReadOnly() bool {
 }
 
 type ModelResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Json          []byte                 `protobuf:"bytes,1,opt,name=json,proto3" json:"json,omitempty"` // JSON-encoded text per RFC7951.
 	unknownFields protoimpl.UnknownFields
-
-	Json []byte `protobuf:"bytes,1,opt,name=json,proto3" json:"json,omitempty"` // JSON-encoded text per RFC7951.
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *ModelResponse) Reset() {
@@ -506,12 +499,11 @@ func (x *ModelResponse) GetJson() []byte {
 }
 
 type DiffRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Original      []byte                 `protobuf:"bytes,1,opt,name=original,proto3" json:"original,omitempty"` // JSON-encoded text per RFC7951.
+	Modified      []byte                 `protobuf:"bytes,2,opt,name=modified,proto3" json:"modified,omitempty"` // JSON-encoded text per RFC7951.
 	unknownFields protoimpl.UnknownFields
-
-	Original []byte `protobuf:"bytes,1,opt,name=original,proto3" json:"original,omitempty"` // JSON-encoded text per RFC7951.
-	Modified []byte `protobuf:"bytes,2,opt,name=modified,proto3" json:"modified,omitempty"` // JSON-encoded text per RFC7951.
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DiffRequest) Reset() {
@@ -559,11 +551,10 @@ func (x *DiffRequest) GetModified() []byte {
 }
 
 type DiffResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Notification  *gnmi.Notification     `protobuf:"bytes,1,opt,name=notification,proto3" json:"notification,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Notification *gnmi.Notification `protobuf:"bytes,1,opt,name=notification,proto3" json:"notification,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DiffResponse) Reset() {
@@ -604,13 +595,12 @@ func (x *DiffResponse) GetNotification() *gnmi.Notification {
 }
 
 type ValidateChangeRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState      `protogen:"open.v1"`
+	Operation     networkelement.ApiOperation `protobuf:"varint,1,opt,name=operation,proto3,enum=gosdn.networkelement.ApiOperation" json:"operation,omitempty"`
+	Path          *gnmi.Path                  `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
+	Value         *gnmi.TypedValue            `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Operation networkelement.ApiOperation `protobuf:"varint,1,opt,name=operation,proto3,enum=gosdn.networkelement.ApiOperation" json:"operation,omitempty"`
-	Path      *gnmi.Path                  `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
-	Value     *gnmi.TypedValue            `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *ValidateChangeRequest) Reset() {
@@ -665,11 +655,10 @@ func (x *ValidateChangeRequest) GetValue() *gnmi.TypedValue {
 }
 
 type ValidateChangeResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Model         []byte                 `protobuf:"bytes,1,opt,name=model,proto3" json:"model,omitempty"` // JSON-encoded text per RFC7951.
 	unknownFields protoimpl.UnknownFields
-
-	Model []byte `protobuf:"bytes,1,opt,name=model,proto3" json:"model,omitempty"` // JSON-encoded text per RFC7951.
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *ValidateChangeResponse) Reset() {
@@ -710,11 +699,10 @@ func (x *ValidateChangeResponse) GetModel() []byte {
 }
 
 type PruneConfigFalseRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Value         []byte                 `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` // JSON-encoded text per RFC7951.
 	unknownFields protoimpl.UnknownFields
-
-	Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` // JSON-encoded text per RFC7951.
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *PruneConfigFalseRequest) Reset() {
@@ -755,11 +743,10 @@ func (x *PruneConfigFalseRequest) GetValue() []byte {
 }
 
 type PruneConfigFalseResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Model         []byte                 `protobuf:"bytes,1,opt,name=model,proto3" json:"model,omitempty"` // JSON-encoded text per RFC7951.
 	unknownFields protoimpl.UnknownFields
-
-	Model []byte `protobuf:"bytes,1,opt,name=model,proto3" json:"model,omitempty"` // JSON-encoded text per RFC7951.
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *PruneConfigFalseResponse) Reset() {
@@ -800,9 +787,9 @@ func (x *PruneConfigFalseResponse) GetModel() []byte {
 }
 
 type SchemaTreeGzipRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
 	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *SchemaTreeGzipRequest) Reset() {
@@ -836,11 +823,10 @@ func (*SchemaTreeGzipRequest) Descriptor() ([]byte, []int) {
 }
 
 type Payload struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Chunk         []byte                 `protobuf:"bytes,1,opt,name=chunk,proto3" json:"chunk,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Chunk []byte `protobuf:"bytes,1,opt,name=chunk,proto3" json:"chunk,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Payload) Reset() {
@@ -880,9 +866,53 @@ func (x *Payload) GetChunk() []byte {
 	return nil
 }
 
+type GetAvailablePluginsRequest struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *GetAvailablePluginsRequest) Reset() {
+	*x = GetAvailablePluginsRequest{}
+	mi := &file_gosdn_plugin_plugin_proto_msgTypes[18]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *GetAvailablePluginsRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GetAvailablePluginsRequest) ProtoMessage() {}
+
+func (x *GetAvailablePluginsRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_gosdn_plugin_plugin_proto_msgTypes[18]
+	if x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use GetAvailablePluginsRequest.ProtoReflect.Descriptor instead.
+func (*GetAvailablePluginsRequest) Descriptor() ([]byte, []int) {
+	return file_gosdn_plugin_plugin_proto_rawDescGZIP(), []int{18}
+}
+
+func (x *GetAvailablePluginsRequest) GetTimestamp() int64 {
+	if x != nil {
+		return x.Timestamp
+	}
+	return 0
+}
+
 var File_gosdn_plugin_plugin_proto protoreflect.FileDescriptor
 
-var file_gosdn_plugin_plugin_proto_rawDesc = []byte{
+var file_gosdn_plugin_plugin_proto_rawDesc = string([]byte{
 	0x0a, 0x19, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x70,
 	0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x67, 0x6f, 0x73,
 	0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x1a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75,
@@ -890,188 +920,205 @@ var file_gosdn_plugin_plugin_proto_rawDesc = []byte{
 	0x2f, 0x67, 0x6e, 0x6d, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6e, 0x6d, 0x69,
 	0x2f, 0x67, 0x6e, 0x6d, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x62, 0x75, 0x66,
 	0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61,
-	0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x29, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f,
-	0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2f, 0x6e,
-	0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72,
-	0x6f, 0x74, 0x6f, 0x22, 0x7e, 0x0a, 0x10, 0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6a, 0x73, 0x6f, 0x6e, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x6a, 0x73, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x04, 0x70,
+	0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+	0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x29, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x6e, 0x65,
+	0x74, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2f, 0x6e, 0x65, 0x74,
+	0x77, 0x6f, 0x72, 0x6b, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+	0x6f, 0x1a, 0x2b, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2d,
+	0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2d,
+	0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x7e,
+	0x0a, 0x10, 0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c,
+	0x52, 0x04, 0x6a, 0x73, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x67, 0x6e, 0x6d, 0x69, 0x2e, 0x50, 0x61, 0x74, 0x68,
+	0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x2e,
+	0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e,
+	0x67, 0x6e, 0x6d, 0x69, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42,
+	0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x29,
+	0x0a, 0x11, 0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f,
+	0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x22, 0x68, 0x0a, 0x0e, 0x53, 0x65, 0x74,
+	0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x04, 0x70,
 	0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x67, 0x6e, 0x6d, 0x69,
 	0x2e, 0x50, 0x61, 0x74, 0x68, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x70,
 	0x61, 0x74, 0x68, 0x12, 0x2e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01,
 	0x28, 0x0b, 0x32, 0x10, 0x2e, 0x67, 0x6e, 0x6d, 0x69, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x56,
 	0x61, 0x6c, 0x75, 0x65, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x05, 0x76, 0x61,
-	0x6c, 0x75, 0x65, 0x22, 0x29, 0x0a, 0x11, 0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c,
+	0x6c, 0x75, 0x65, 0x22, 0x27, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65,
+	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x22, 0x7a, 0x0a, 0x0e,
+	0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26,
+	0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x67,
+	0x6e, 0x6d, 0x69, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01,
+	0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x40, 0x0a, 0x17, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x46, 0x6f, 0x72, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74,
+	0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52,
+	0x17, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x46, 0x6f, 0x72, 0x49, 0x6e, 0x74, 0x65, 0x6e,
+	0x64, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0x3b, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4e,
+	0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x05, 0x6e,
+	0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x6e, 0x6d,
+	0x69, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x05,
+	0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3b, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e,
+	0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x04, 0x70, 0x61,
+	0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x67, 0x6e, 0x6d, 0x69, 0x2e,
+	0x50, 0x61, 0x74, 0x68, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x70, 0x61,
+	0x74, 0x68, 0x22, 0x2a, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65,
 	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x69,
-	0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x22, 0x68,
-	0x0a, 0x0e, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x12, 0x26, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a,
-	0x2e, 0x67, 0x6e, 0x6d, 0x69, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8,
-	0x01, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x2e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
-	0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x67, 0x6e, 0x6d, 0x69, 0x2e, 0x54,
-	0x79, 0x70, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01,
-	0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x27, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x4e,
-	0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76,
-	0x61, 0x6c, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x69,
-	0x64, 0x22, 0x7a, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x0b, 0x32, 0x0a, 0x2e, 0x67, 0x6e, 0x6d, 0x69, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x42, 0x06, 0xba,
-	0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x40, 0x0a, 0x17, 0x72,
-	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x46, 0x6f, 0x72, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x65,
-	0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x42, 0x06, 0xba, 0x48,
-	0x03, 0xc8, 0x01, 0x01, 0x52, 0x17, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x46, 0x6f, 0x72,
-	0x49, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0x3b, 0x0a,
-	0x0f, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
-	0x12, 0x28, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
-	0x12, 0x2e, 0x67, 0x6e, 0x6d, 0x69, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
-	0x69, 0x6f, 0x6e, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3b, 0x0a, 0x11, 0x44, 0x65,
-	0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
-	0x26, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e,
-	0x67, 0x6e, 0x6d, 0x69, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01,
-	0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x2a, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74,
-	0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a,
-	0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61,
-	0x6c, 0x69, 0x64, 0x22, 0x3e, 0x0a, 0x0c, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x0e, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x65, 0x61,
-	0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x42, 0x06, 0xba, 0x48, 0x03,
-	0xc8, 0x01, 0x01, 0x52, 0x0e, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x65, 0x61, 0x64, 0x4f,
-	0x6e, 0x6c, 0x79, 0x22, 0x23, 0x0a, 0x0d, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x0c, 0x52, 0x04, 0x6a, 0x73, 0x6f, 0x6e, 0x22, 0x55, 0x0a, 0x0b, 0x44, 0x69, 0x66, 0x66,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x22, 0x0a, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69,
-	0x6e, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01,
-	0x01, 0x52, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x12, 0x22, 0x0a, 0x08, 0x6d,
-	0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0xba,
-	0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x08, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x22,
-	0x46, 0x0a, 0x0c, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
-	0x36, 0x0a, 0x0c, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x6e, 0x6d, 0x69, 0x2e, 0x4e, 0x6f, 0x74,
-	0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x6e, 0x6f, 0x74, 0x69, 0x66,
-	0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb9, 0x01, 0x0a, 0x15, 0x56, 0x61, 0x6c, 0x69,
-	0x64, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x12, 0x48, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x6e, 0x65, 0x74,
-	0x77, 0x6f, 0x72, 0x6b, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x70, 0x69, 0x4f,
-	0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01,
-	0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x04, 0x70,
-	0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x67, 0x6e, 0x6d, 0x69,
-	0x2e, 0x50, 0x61, 0x74, 0x68, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x70,
-	0x61, 0x74, 0x68, 0x12, 0x2e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01,
-	0x28, 0x0b, 0x32, 0x10, 0x2e, 0x67, 0x6e, 0x6d, 0x69, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x56,
-	0x61, 0x6c, 0x75, 0x65, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x05, 0x76, 0x61,
-	0x6c, 0x75, 0x65, 0x22, 0x2e, 0x0a, 0x16, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43,
-	0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a,
-	0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x6d, 0x6f,
-	0x64, 0x65, 0x6c, 0x22, 0x37, 0x0a, 0x17, 0x50, 0x72, 0x75, 0x6e, 0x65, 0x43, 0x6f, 0x6e, 0x66,
-	0x69, 0x67, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c,
-	0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0xba,
-	0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x30, 0x0a, 0x18,
-	0x50, 0x72, 0x75, 0x6e, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x61, 0x6c, 0x73, 0x65,
+	0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x22, 0x3e,
+	0x0a, 0x0c, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e,
+	0x0a, 0x0e, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0e,
+	0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x23,
+	0x0a, 0x0d, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
+	0x12, 0x0a, 0x04, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x6a,
+	0x73, 0x6f, 0x6e, 0x22, 0x55, 0x0a, 0x0b, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x12, 0x22, 0x0a, 0x08, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x08, 0x6f, 0x72,
+	0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x12, 0x22, 0x0a, 0x08, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69,
+	0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01,
+	0x52, 0x08, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x22, 0x46, 0x0a, 0x0c, 0x44, 0x69,
+	0x66, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x0c, 0x6e, 0x6f,
+	0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
+	0x32, 0x12, 0x2e, 0x67, 0x6e, 0x6d, 0x69, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
+	0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69,
+	0x6f, 0x6e, 0x22, 0xb9, 0x01, 0x0a, 0x15, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43,
+	0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x48, 0x0a, 0x09,
+	0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32,
+	0x22, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x65,
+	0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x70, 0x69, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74,
+	0x69, 0x6f, 0x6e, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x09, 0x6f, 0x70, 0x65,
+	0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x67, 0x6e, 0x6d, 0x69, 0x2e, 0x50, 0x61, 0x74, 0x68,
+	0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x2e,
+	0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e,
+	0x67, 0x6e, 0x6d, 0x69, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42,
+	0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2e,
+	0x0a, 0x16, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65,
 	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65,
-	0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x22, 0x17,
-	0x0a, 0x15, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x54, 0x72, 0x65, 0x65, 0x47, 0x7a, 0x69, 0x70,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x1f, 0x0a, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f,
-	0x61, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x0c, 0x52, 0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x32, 0xc8, 0x05, 0x0a, 0x06, 0x50, 0x6c, 0x75,
-	0x67, 0x69, 0x6e, 0x12, 0x4c, 0x0a, 0x09, 0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c,
-	0x12, 0x1e, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e,
-	0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x1f, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e,
-	0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
-	0x65, 0x12, 0x46, 0x0a, 0x07, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x67,
-	0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x4e,
-	0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x73,
-	0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x64,
-	0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x07, 0x47, 0x65, 0x74,
-	0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75,
-	0x67, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69,
-	0x6e, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
-	0x65, 0x12, 0x4f, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12,
-	0x1f, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x44,
-	0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
-	0x1a, 0x20, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e,
-	0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
-	0x73, 0x65, 0x12, 0x40, 0x0a, 0x05, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x1a, 0x2e, 0x67, 0x6f,
-	0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x6c,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e,
-	0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x44, 0x69, 0x66, 0x66, 0x12, 0x19, 0x2e, 0x67,
-	0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x44, 0x69, 0x66, 0x66,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e,
-	0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f,
-	0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x54, 0x72, 0x65,
-	0x65, 0x47, 0x7a, 0x69, 0x70, 0x12, 0x23, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c,
-	0x75, 0x67, 0x69, 0x6e, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x54, 0x72, 0x65, 0x65, 0x47,
-	0x7a, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x67, 0x6f, 0x73,
-	0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61,
-	0x64, 0x30, 0x01, 0x12, 0x5b, 0x0a, 0x0e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43,
-	0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x23, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c,
-	0x75, 0x67, 0x69, 0x6e, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61,
-	0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x67, 0x6f, 0x73,
-	0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61,
-	0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
-	0x12, 0x61, 0x0a, 0x10, 0x50, 0x72, 0x75, 0x6e, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46,
-	0x61, 0x6c, 0x73, 0x65, 0x12, 0x25, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75,
-	0x67, 0x69, 0x6e, 0x2e, 0x50, 0x72, 0x75, 0x6e, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46,
-	0x61, 0x6c, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x67, 0x6f,
-	0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x50, 0x72, 0x75, 0x6e, 0x65,
+	0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x22, 0x37,
+	0x0a, 0x17, 0x50, 0x72, 0x75, 0x6e, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x61, 0x6c,
+	0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x05, 0x76, 0x61, 0x6c,
+	0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01,
+	0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x30, 0x0a, 0x18, 0x50, 0x72, 0x75, 0x6e, 0x65,
 	0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
-	0x6e, 0x73, 0x65, 0x42, 0x32, 0x5a, 0x30, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x66, 0x62, 0x69, 0x2e,
-	0x68, 0x2d, 0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67, 0x6f,
-	0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e,
-	0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+	0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x0c, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x22, 0x17, 0x0a, 0x15, 0x53, 0x63, 0x68,
+	0x65, 0x6d, 0x61, 0x54, 0x72, 0x65, 0x65, 0x47, 0x7a, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x22, 0x1f, 0x0a, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x14, 0x0a,
+	0x05, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68,
+	0x75, 0x6e, 0x6b, 0x22, 0x3a, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61,
+	0x62, 0x6c, 0x65, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x32,
+	0xad, 0x06, 0x0a, 0x06, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x12, 0x4c, 0x0a, 0x09, 0x55, 0x6e,
+	0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x12, 0x1e, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e,
+	0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e,
+	0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x55, 0x6e, 0x6d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x07, 0x53, 0x65, 0x74, 0x4e,
+	0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67,
+	0x69, 0x6e, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e,
+	0x2e, 0x53, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x12, 0x46, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f,
+	0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f,
+	0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x6f, 0x73, 0x64,
+	0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65,
+	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65,
+	0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70,
+	0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e,
+	0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4e, 0x6f, 0x64,
+	0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x05, 0x4d, 0x6f, 0x64,
+	0x65, 0x6c, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69,
+	0x6e, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b,
+	0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x4d, 0x6f,
+	0x64, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x44,
+	0x69, 0x66, 0x66, 0x12, 0x19, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67,
+	0x69, 0x6e, 0x2e, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a,
+	0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x44, 0x69,
+	0x66, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0e, 0x53, 0x63,
+	0x68, 0x65, 0x6d, 0x61, 0x54, 0x72, 0x65, 0x65, 0x47, 0x7a, 0x69, 0x70, 0x12, 0x23, 0x2e, 0x67,
+	0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x53, 0x63, 0x68, 0x65,
+	0x6d, 0x61, 0x54, 0x72, 0x65, 0x65, 0x47, 0x7a, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x1a, 0x15, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e,
+	0x2e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x30, 0x01, 0x12, 0x5b, 0x0a, 0x0e, 0x56, 0x61,
+	0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x23, 0x2e, 0x67,
+	0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x56, 0x61, 0x6c, 0x69,
+	0x64, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+	0x74, 0x1a, 0x24, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e,
+	0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x10, 0x50, 0x72, 0x75, 0x6e, 0x65,
+	0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x12, 0x25, 0x2e, 0x67, 0x6f,
+	0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x50, 0x72, 0x75, 0x6e, 0x65,
+	0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
+	0x73, 0x74, 0x1a, 0x26, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69,
+	0x6e, 0x2e, 0x50, 0x72, 0x75, 0x6e, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x61, 0x6c,
+	0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x13, 0x47, 0x65,
+	0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e,
+	0x73, 0x12, 0x28, 0x2e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e,
+	0x2e, 0x47, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x6c, 0x75,
+	0x67, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x67, 0x6f,
+	0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73,
+	0x74, 0x72, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42,
+	0x32, 0x5a, 0x30, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x66, 0x62, 0x69, 0x2e, 0x68, 0x2d, 0x64, 0x61,
+	0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f,
+	0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x70, 0x6c, 0x75,
+	0x67, 0x69, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+})
 
 var (
 	file_gosdn_plugin_plugin_proto_rawDescOnce sync.Once
-	file_gosdn_plugin_plugin_proto_rawDescData = file_gosdn_plugin_plugin_proto_rawDesc
+	file_gosdn_plugin_plugin_proto_rawDescData []byte
 )
 
 func file_gosdn_plugin_plugin_proto_rawDescGZIP() []byte {
 	file_gosdn_plugin_plugin_proto_rawDescOnce.Do(func() {
-		file_gosdn_plugin_plugin_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdn_plugin_plugin_proto_rawDescData)
+		file_gosdn_plugin_plugin_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gosdn_plugin_plugin_proto_rawDesc), len(file_gosdn_plugin_plugin_proto_rawDesc)))
 	})
 	return file_gosdn_plugin_plugin_proto_rawDescData
 }
 
-var file_gosdn_plugin_plugin_proto_msgTypes = make([]protoimpl.MessageInfo, 18)
+var file_gosdn_plugin_plugin_proto_msgTypes = make([]protoimpl.MessageInfo, 19)
 var file_gosdn_plugin_plugin_proto_goTypes = []any{
-	(*UnmarshalRequest)(nil),         // 0: gosdn.plugin.UnmarshalRequest
-	(*UnmarshalResponse)(nil),        // 1: gosdn.plugin.UnmarshalResponse
-	(*SetNodeRequest)(nil),           // 2: gosdn.plugin.SetNodeRequest
-	(*SetNodeResponse)(nil),          // 3: gosdn.plugin.SetNodeResponse
-	(*GetNodeRequest)(nil),           // 4: gosdn.plugin.GetNodeRequest
-	(*GetNodeResponse)(nil),          // 5: gosdn.plugin.GetNodeResponse
-	(*DeleteNodeRequest)(nil),        // 6: gosdn.plugin.DeleteNodeRequest
-	(*DeleteNodeResponse)(nil),       // 7: gosdn.plugin.DeleteNodeResponse
-	(*ModelRequest)(nil),             // 8: gosdn.plugin.ModelRequest
-	(*ModelResponse)(nil),            // 9: gosdn.plugin.ModelResponse
-	(*DiffRequest)(nil),              // 10: gosdn.plugin.DiffRequest
-	(*DiffResponse)(nil),             // 11: gosdn.plugin.DiffResponse
-	(*ValidateChangeRequest)(nil),    // 12: gosdn.plugin.ValidateChangeRequest
-	(*ValidateChangeResponse)(nil),   // 13: gosdn.plugin.ValidateChangeResponse
-	(*PruneConfigFalseRequest)(nil),  // 14: gosdn.plugin.PruneConfigFalseRequest
-	(*PruneConfigFalseResponse)(nil), // 15: gosdn.plugin.PruneConfigFalseResponse
-	(*SchemaTreeGzipRequest)(nil),    // 16: gosdn.plugin.SchemaTreeGzipRequest
-	(*Payload)(nil),                  // 17: gosdn.plugin.Payload
-	(*gnmi.Path)(nil),                // 18: gnmi.Path
-	(*gnmi.TypedValue)(nil),          // 19: gnmi.TypedValue
-	(*gnmi.Notification)(nil),        // 20: gnmi.Notification
-	(networkelement.ApiOperation)(0), // 21: gosdn.networkelement.ApiOperation
+	(*UnmarshalRequest)(nil),            // 0: gosdn.plugin.UnmarshalRequest
+	(*UnmarshalResponse)(nil),           // 1: gosdn.plugin.UnmarshalResponse
+	(*SetNodeRequest)(nil),              // 2: gosdn.plugin.SetNodeRequest
+	(*SetNodeResponse)(nil),             // 3: gosdn.plugin.SetNodeResponse
+	(*GetNodeRequest)(nil),              // 4: gosdn.plugin.GetNodeRequest
+	(*GetNodeResponse)(nil),             // 5: gosdn.plugin.GetNodeResponse
+	(*DeleteNodeRequest)(nil),           // 6: gosdn.plugin.DeleteNodeRequest
+	(*DeleteNodeResponse)(nil),          // 7: gosdn.plugin.DeleteNodeResponse
+	(*ModelRequest)(nil),                // 8: gosdn.plugin.ModelRequest
+	(*ModelResponse)(nil),               // 9: gosdn.plugin.ModelResponse
+	(*DiffRequest)(nil),                 // 10: gosdn.plugin.DiffRequest
+	(*DiffResponse)(nil),                // 11: gosdn.plugin.DiffResponse
+	(*ValidateChangeRequest)(nil),       // 12: gosdn.plugin.ValidateChangeRequest
+	(*ValidateChangeResponse)(nil),      // 13: gosdn.plugin.ValidateChangeResponse
+	(*PruneConfigFalseRequest)(nil),     // 14: gosdn.plugin.PruneConfigFalseRequest
+	(*PruneConfigFalseResponse)(nil),    // 15: gosdn.plugin.PruneConfigFalseResponse
+	(*SchemaTreeGzipRequest)(nil),       // 16: gosdn.plugin.SchemaTreeGzipRequest
+	(*Payload)(nil),                     // 17: gosdn.plugin.Payload
+	(*GetAvailablePluginsRequest)(nil),  // 18: gosdn.plugin.GetAvailablePluginsRequest
+	(*gnmi.Path)(nil),                   // 19: gnmi.Path
+	(*gnmi.TypedValue)(nil),             // 20: gnmi.TypedValue
+	(*gnmi.Notification)(nil),           // 21: gnmi.Notification
+	(networkelement.ApiOperation)(0),    // 22: gosdn.networkelement.ApiOperation
+	(*plugin_registry.GetResponse)(nil), // 23: gosdn.plugin_registry.GetResponse
 }
 var file_gosdn_plugin_plugin_proto_depIdxs = []int32{
-	18, // 0: gosdn.plugin.UnmarshalRequest.path:type_name -> gnmi.Path
-	19, // 1: gosdn.plugin.UnmarshalRequest.value:type_name -> gnmi.TypedValue
-	18, // 2: gosdn.plugin.SetNodeRequest.path:type_name -> gnmi.Path
-	19, // 3: gosdn.plugin.SetNodeRequest.value:type_name -> gnmi.TypedValue
-	18, // 4: gosdn.plugin.GetNodeRequest.path:type_name -> gnmi.Path
-	20, // 5: gosdn.plugin.GetNodeResponse.nodes:type_name -> gnmi.Notification
-	18, // 6: gosdn.plugin.DeleteNodeRequest.path:type_name -> gnmi.Path
-	20, // 7: gosdn.plugin.DiffResponse.notification:type_name -> gnmi.Notification
-	21, // 8: gosdn.plugin.ValidateChangeRequest.operation:type_name -> gosdn.networkelement.ApiOperation
-	18, // 9: gosdn.plugin.ValidateChangeRequest.path:type_name -> gnmi.Path
-	19, // 10: gosdn.plugin.ValidateChangeRequest.value:type_name -> gnmi.TypedValue
+	19, // 0: gosdn.plugin.UnmarshalRequest.path:type_name -> gnmi.Path
+	20, // 1: gosdn.plugin.UnmarshalRequest.value:type_name -> gnmi.TypedValue
+	19, // 2: gosdn.plugin.SetNodeRequest.path:type_name -> gnmi.Path
+	20, // 3: gosdn.plugin.SetNodeRequest.value:type_name -> gnmi.TypedValue
+	19, // 4: gosdn.plugin.GetNodeRequest.path:type_name -> gnmi.Path
+	21, // 5: gosdn.plugin.GetNodeResponse.nodes:type_name -> gnmi.Notification
+	19, // 6: gosdn.plugin.DeleteNodeRequest.path:type_name -> gnmi.Path
+	21, // 7: gosdn.plugin.DiffResponse.notification:type_name -> gnmi.Notification
+	22, // 8: gosdn.plugin.ValidateChangeRequest.operation:type_name -> gosdn.networkelement.ApiOperation
+	19, // 9: gosdn.plugin.ValidateChangeRequest.path:type_name -> gnmi.Path
+	20, // 10: gosdn.plugin.ValidateChangeRequest.value:type_name -> gnmi.TypedValue
 	0,  // 11: gosdn.plugin.Plugin.Unmarshal:input_type -> gosdn.plugin.UnmarshalRequest
 	2,  // 12: gosdn.plugin.Plugin.SetNode:input_type -> gosdn.plugin.SetNodeRequest
 	4,  // 13: gosdn.plugin.Plugin.GetNode:input_type -> gosdn.plugin.GetNodeRequest
@@ -1081,17 +1128,19 @@ var file_gosdn_plugin_plugin_proto_depIdxs = []int32{
 	16, // 17: gosdn.plugin.Plugin.SchemaTreeGzip:input_type -> gosdn.plugin.SchemaTreeGzipRequest
 	12, // 18: gosdn.plugin.Plugin.ValidateChange:input_type -> gosdn.plugin.ValidateChangeRequest
 	14, // 19: gosdn.plugin.Plugin.PruneConfigFalse:input_type -> gosdn.plugin.PruneConfigFalseRequest
-	1,  // 20: gosdn.plugin.Plugin.Unmarshal:output_type -> gosdn.plugin.UnmarshalResponse
-	3,  // 21: gosdn.plugin.Plugin.SetNode:output_type -> gosdn.plugin.SetNodeResponse
-	5,  // 22: gosdn.plugin.Plugin.GetNode:output_type -> gosdn.plugin.GetNodeResponse
-	7,  // 23: gosdn.plugin.Plugin.DeleteNode:output_type -> gosdn.plugin.DeleteNodeResponse
-	9,  // 24: gosdn.plugin.Plugin.Model:output_type -> gosdn.plugin.ModelResponse
-	11, // 25: gosdn.plugin.Plugin.Diff:output_type -> gosdn.plugin.DiffResponse
-	17, // 26: gosdn.plugin.Plugin.SchemaTreeGzip:output_type -> gosdn.plugin.Payload
-	13, // 27: gosdn.plugin.Plugin.ValidateChange:output_type -> gosdn.plugin.ValidateChangeResponse
-	15, // 28: gosdn.plugin.Plugin.PruneConfigFalse:output_type -> gosdn.plugin.PruneConfigFalseResponse
-	20, // [20:29] is the sub-list for method output_type
-	11, // [11:20] is the sub-list for method input_type
+	18, // 20: gosdn.plugin.Plugin.GetAvailablePlugins:input_type -> gosdn.plugin.GetAvailablePluginsRequest
+	1,  // 21: gosdn.plugin.Plugin.Unmarshal:output_type -> gosdn.plugin.UnmarshalResponse
+	3,  // 22: gosdn.plugin.Plugin.SetNode:output_type -> gosdn.plugin.SetNodeResponse
+	5,  // 23: gosdn.plugin.Plugin.GetNode:output_type -> gosdn.plugin.GetNodeResponse
+	7,  // 24: gosdn.plugin.Plugin.DeleteNode:output_type -> gosdn.plugin.DeleteNodeResponse
+	9,  // 25: gosdn.plugin.Plugin.Model:output_type -> gosdn.plugin.ModelResponse
+	11, // 26: gosdn.plugin.Plugin.Diff:output_type -> gosdn.plugin.DiffResponse
+	17, // 27: gosdn.plugin.Plugin.SchemaTreeGzip:output_type -> gosdn.plugin.Payload
+	13, // 28: gosdn.plugin.Plugin.ValidateChange:output_type -> gosdn.plugin.ValidateChangeResponse
+	15, // 29: gosdn.plugin.Plugin.PruneConfigFalse:output_type -> gosdn.plugin.PruneConfigFalseResponse
+	23, // 30: gosdn.plugin.Plugin.GetAvailablePlugins:output_type -> gosdn.plugin_registry.GetResponse
+	21, // [21:31] is the sub-list for method output_type
+	11, // [11:21] is the sub-list for method input_type
 	11, // [11:11] is the sub-list for extension type_name
 	11, // [11:11] is the sub-list for extension extendee
 	0,  // [0:11] is the sub-list for field type_name
@@ -1106,9 +1155,9 @@ func file_gosdn_plugin_plugin_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdn_plugin_plugin_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_gosdn_plugin_plugin_proto_rawDesc), len(file_gosdn_plugin_plugin_proto_rawDesc)),
 			NumEnums:      0,
-			NumMessages:   18,
+			NumMessages:   19,
 			NumExtensions: 0,
 			NumServices:   1,
 		},
@@ -1117,7 +1166,6 @@ func file_gosdn_plugin_plugin_proto_init() {
 		MessageInfos:      file_gosdn_plugin_plugin_proto_msgTypes,
 	}.Build()
 	File_gosdn_plugin_plugin_proto = out.File
-	file_gosdn_plugin_plugin_proto_rawDesc = nil
 	file_gosdn_plugin_plugin_proto_goTypes = nil
 	file_gosdn_plugin_plugin_proto_depIdxs = nil
 }
diff --git a/api/go/gosdn/plugin/plugin.pb.gw.go b/api/go/gosdn/plugin/plugin.pb.gw.go
new file mode 100644
index 000000000..745f6cadd
--- /dev/null
+++ b/api/go/gosdn/plugin/plugin.pb.gw.go
@@ -0,0 +1,162 @@
+// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
+// source: gosdn/plugin/plugin.proto
+
+/*
+Package plugin is a reverse proxy.
+
+It translates gRPC into RESTful JSON APIs.
+*/
+package plugin
+
+import (
+	"context"
+	"errors"
+	"io"
+	"net/http"
+
+	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
+	"github.com/grpc-ecosystem/grpc-gateway/v2/utilities"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/grpclog"
+	"google.golang.org/grpc/metadata"
+	"google.golang.org/grpc/status"
+	"google.golang.org/protobuf/proto"
+)
+
+// Suppress "imported and not used" errors
+var (
+	_ codes.Code
+	_ io.Reader
+	_ status.Status
+	_ = errors.New
+	_ = runtime.String
+	_ = utilities.NewDoubleArray
+	_ = metadata.Join
+)
+
+var filter_Plugin_GetAvailablePlugins_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
+
+func request_Plugin_GetAvailablePlugins_0(ctx context.Context, marshaler runtime.Marshaler, client PluginClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+	var (
+		protoReq GetAvailablePluginsRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := req.ParseForm(); err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Plugin_GetAvailablePlugins_0); err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	msg, err := client.GetAvailablePlugins(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+	return msg, metadata, err
+}
+
+func local_request_Plugin_GetAvailablePlugins_0(ctx context.Context, marshaler runtime.Marshaler, server PluginServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+	var (
+		protoReq GetAvailablePluginsRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := req.ParseForm(); err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Plugin_GetAvailablePlugins_0); err != nil {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	msg, err := server.GetAvailablePlugins(ctx, &protoReq)
+	return msg, metadata, err
+}
+
+// RegisterPluginHandlerServer registers the http handlers for service Plugin to "mux".
+// UnaryRPC     :call PluginServer directly.
+// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
+// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterPluginHandlerFromEndpoint instead.
+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
+func RegisterPluginHandlerServer(ctx context.Context, mux *runtime.ServeMux, server PluginServer) error {
+	mux.Handle(http.MethodGet, pattern_Plugin_GetAvailablePlugins_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+		ctx, cancel := context.WithCancel(req.Context())
+		defer cancel()
+		var stream runtime.ServerTransportStream
+		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
+		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.plugin.Plugin/GetAvailablePlugins", runtime.WithHTTPPathPattern("/plugins/plugin"))
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+		resp, md, err := local_request_Plugin_GetAvailablePlugins_0(annotatedContext, inboundMarshaler, server, req, pathParams)
+		md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
+		annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
+		if err != nil {
+			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
+			return
+		}
+		forward_Plugin_GetAvailablePlugins_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+	})
+
+	return nil
+}
+
+// RegisterPluginHandlerFromEndpoint is same as RegisterPluginHandler but
+// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
+func RegisterPluginHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
+	conn, err := grpc.NewClient(endpoint, opts...)
+	if err != nil {
+		return err
+	}
+	defer func() {
+		if err != nil {
+			if cerr := conn.Close(); cerr != nil {
+				grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
+			}
+			return
+		}
+		go func() {
+			<-ctx.Done()
+			if cerr := conn.Close(); cerr != nil {
+				grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
+			}
+		}()
+	}()
+	return RegisterPluginHandler(ctx, mux, conn)
+}
+
+// RegisterPluginHandler registers the http handlers for service Plugin to "mux".
+// The handlers forward requests to the grpc endpoint over "conn".
+func RegisterPluginHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
+	return RegisterPluginHandlerClient(ctx, mux, NewPluginClient(conn))
+}
+
+// RegisterPluginHandlerClient registers the http handlers for service Plugin
+// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "PluginClient".
+// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "PluginClient"
+// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
+// "PluginClient" to call the correct interceptors. This client ignores the HTTP middlewares.
+func RegisterPluginHandlerClient(ctx context.Context, mux *runtime.ServeMux, client PluginClient) error {
+	mux.Handle(http.MethodGet, pattern_Plugin_GetAvailablePlugins_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+		ctx, cancel := context.WithCancel(req.Context())
+		defer cancel()
+		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.plugin.Plugin/GetAvailablePlugins", runtime.WithHTTPPathPattern("/plugins/plugin"))
+		if err != nil {
+			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+			return
+		}
+		resp, md, err := request_Plugin_GetAvailablePlugins_0(annotatedContext, inboundMarshaler, client, req, pathParams)
+		annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
+		if err != nil {
+			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
+			return
+		}
+		forward_Plugin_GetAvailablePlugins_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+	})
+	return nil
+}
+
+var (
+	pattern_Plugin_GetAvailablePlugins_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"plugins", "plugin"}, ""))
+)
+
+var (
+	forward_Plugin_GetAvailablePlugins_0 = runtime.ForwardResponseMessage
+)
diff --git a/api/go/gosdn/plugin/plugin_grpc.pb.go b/api/go/gosdn/plugin/plugin_grpc.pb.go
index e524b8c4b..ec194d82d 100755
--- a/api/go/gosdn/plugin/plugin_grpc.pb.go
+++ b/api/go/gosdn/plugin/plugin_grpc.pb.go
@@ -7,6 +7,7 @@
 package plugin
 
 import (
+	plugin_registry "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/plugin-registry"
 	context "context"
 	grpc "google.golang.org/grpc"
 	codes "google.golang.org/grpc/codes"
@@ -19,15 +20,16 @@ import (
 const _ = grpc.SupportPackageIsVersion9
 
 const (
-	Plugin_Unmarshal_FullMethodName        = "/gosdn.plugin.Plugin/Unmarshal"
-	Plugin_SetNode_FullMethodName          = "/gosdn.plugin.Plugin/SetNode"
-	Plugin_GetNode_FullMethodName          = "/gosdn.plugin.Plugin/GetNode"
-	Plugin_DeleteNode_FullMethodName       = "/gosdn.plugin.Plugin/DeleteNode"
-	Plugin_Model_FullMethodName            = "/gosdn.plugin.Plugin/Model"
-	Plugin_Diff_FullMethodName             = "/gosdn.plugin.Plugin/Diff"
-	Plugin_SchemaTreeGzip_FullMethodName   = "/gosdn.plugin.Plugin/SchemaTreeGzip"
-	Plugin_ValidateChange_FullMethodName   = "/gosdn.plugin.Plugin/ValidateChange"
-	Plugin_PruneConfigFalse_FullMethodName = "/gosdn.plugin.Plugin/PruneConfigFalse"
+	Plugin_Unmarshal_FullMethodName           = "/gosdn.plugin.Plugin/Unmarshal"
+	Plugin_SetNode_FullMethodName             = "/gosdn.plugin.Plugin/SetNode"
+	Plugin_GetNode_FullMethodName             = "/gosdn.plugin.Plugin/GetNode"
+	Plugin_DeleteNode_FullMethodName          = "/gosdn.plugin.Plugin/DeleteNode"
+	Plugin_Model_FullMethodName               = "/gosdn.plugin.Plugin/Model"
+	Plugin_Diff_FullMethodName                = "/gosdn.plugin.Plugin/Diff"
+	Plugin_SchemaTreeGzip_FullMethodName      = "/gosdn.plugin.Plugin/SchemaTreeGzip"
+	Plugin_ValidateChange_FullMethodName      = "/gosdn.plugin.Plugin/ValidateChange"
+	Plugin_PruneConfigFalse_FullMethodName    = "/gosdn.plugin.Plugin/PruneConfigFalse"
+	Plugin_GetAvailablePlugins_FullMethodName = "/gosdn.plugin.Plugin/GetAvailablePlugins"
 )
 
 // PluginClient is the client API for Plugin service.
@@ -43,6 +45,7 @@ type PluginClient interface {
 	SchemaTreeGzip(ctx context.Context, in *SchemaTreeGzipRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[Payload], error)
 	ValidateChange(ctx context.Context, in *ValidateChangeRequest, opts ...grpc.CallOption) (*ValidateChangeResponse, error)
 	PruneConfigFalse(ctx context.Context, in *PruneConfigFalseRequest, opts ...grpc.CallOption) (*PruneConfigFalseResponse, error)
+	GetAvailablePlugins(ctx context.Context, in *GetAvailablePluginsRequest, opts ...grpc.CallOption) (*plugin_registry.GetResponse, error)
 }
 
 type pluginClient struct {
@@ -152,6 +155,16 @@ func (c *pluginClient) PruneConfigFalse(ctx context.Context, in *PruneConfigFals
 	return out, nil
 }
 
+func (c *pluginClient) GetAvailablePlugins(ctx context.Context, in *GetAvailablePluginsRequest, opts ...grpc.CallOption) (*plugin_registry.GetResponse, error) {
+	cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+	out := new(plugin_registry.GetResponse)
+	err := c.cc.Invoke(ctx, Plugin_GetAvailablePlugins_FullMethodName, in, out, cOpts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
 // PluginServer is the server API for Plugin service.
 // All implementations must embed UnimplementedPluginServer
 // for forward compatibility.
@@ -165,6 +178,7 @@ type PluginServer interface {
 	SchemaTreeGzip(*SchemaTreeGzipRequest, grpc.ServerStreamingServer[Payload]) error
 	ValidateChange(context.Context, *ValidateChangeRequest) (*ValidateChangeResponse, error)
 	PruneConfigFalse(context.Context, *PruneConfigFalseRequest) (*PruneConfigFalseResponse, error)
+	GetAvailablePlugins(context.Context, *GetAvailablePluginsRequest) (*plugin_registry.GetResponse, error)
 	mustEmbedUnimplementedPluginServer()
 }
 
@@ -202,6 +216,9 @@ func (UnimplementedPluginServer) ValidateChange(context.Context, *ValidateChange
 func (UnimplementedPluginServer) PruneConfigFalse(context.Context, *PruneConfigFalseRequest) (*PruneConfigFalseResponse, error) {
 	return nil, status.Errorf(codes.Unimplemented, "method PruneConfigFalse not implemented")
 }
+func (UnimplementedPluginServer) GetAvailablePlugins(context.Context, *GetAvailablePluginsRequest) (*plugin_registry.GetResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method GetAvailablePlugins not implemented")
+}
 func (UnimplementedPluginServer) mustEmbedUnimplementedPluginServer() {}
 func (UnimplementedPluginServer) testEmbeddedByValue()                {}
 
@@ -378,6 +395,24 @@ func _Plugin_PruneConfigFalse_Handler(srv interface{}, ctx context.Context, dec
 	return interceptor(ctx, in, info, handler)
 }
 
+func _Plugin_GetAvailablePlugins_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(GetAvailablePluginsRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(PluginServer).GetAvailablePlugins(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: Plugin_GetAvailablePlugins_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(PluginServer).GetAvailablePlugins(ctx, req.(*GetAvailablePluginsRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
 // Plugin_ServiceDesc is the grpc.ServiceDesc for Plugin service.
 // It's only intended for direct use with grpc.RegisterService,
 // and not to be introspected or modified (even as a copy)
@@ -417,6 +452,10 @@ var Plugin_ServiceDesc = grpc.ServiceDesc{
 			MethodName: "PruneConfigFalse",
 			Handler:    _Plugin_PruneConfigFalse_Handler,
 		},
+		{
+			MethodName: "GetAvailablePlugins",
+			Handler:    _Plugin_GetAvailablePlugins_Handler,
+		},
 	},
 	Streams: []grpc.StreamDesc{
 		{
diff --git a/api/go/gosdn/pnd/pnd.pb.go b/api/go/gosdn/pnd/pnd.pb.go
index 16f5b733d..71b33fdd0 100755
--- a/api/go/gosdn/pnd/pnd.pb.go
+++ b/api/go/gosdn/pnd/pnd.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: gosdn/pnd/pnd.proto
 
@@ -17,6 +17,7 @@ import (
 	_ "google.golang.org/protobuf/types/descriptorpb"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -27,13 +28,12 @@ const (
 )
 
 type PrincipalNetworkDomain struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Id            string                 `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	Name          string                 `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+	Description   string                 `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Id          string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	Name        string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
-	Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *PrincipalNetworkDomain) Reset() {
@@ -88,12 +88,11 @@ func (x *PrincipalNetworkDomain) GetDescription() string {
 }
 
 type GetPndRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Pid           string                 `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Pid       string `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetPndRequest) Reset() {
@@ -141,12 +140,11 @@ func (x *GetPndRequest) GetPid() string {
 }
 
 type GetPndResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState  `protogen:"open.v1"`
+	Timestamp     int64                   `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Pnd           *PrincipalNetworkDomain `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64                   `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Pnd       *PrincipalNetworkDomain `protobuf:"bytes,2,opt,name=pnd,proto3" json:"pnd,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetPndResponse) Reset() {
@@ -194,11 +192,10 @@ func (x *GetPndResponse) GetPnd() *PrincipalNetworkDomain {
 }
 
 type GetPndListRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetPndListRequest) Reset() {
@@ -239,12 +236,11 @@ func (x *GetPndListRequest) GetTimestamp() int64 {
 }
 
 type GetPndListResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState    `protogen:"open.v1"`
+	Timestamp     int64                     `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Pnd           []*PrincipalNetworkDomain `protobuf:"bytes,2,rep,name=pnd,proto3" json:"pnd,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64                     `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Pnd       []*PrincipalNetworkDomain `protobuf:"bytes,2,rep,name=pnd,proto3" json:"pnd,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetPndListResponse) Reset() {
@@ -292,12 +288,11 @@ func (x *GetPndListResponse) GetPnd() []*PrincipalNetworkDomain {
 }
 
 type CreatePndListRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Pnd           []*PndCreateProperties `protobuf:"bytes,2,rep,name=pnd,proto3" json:"pnd,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Pnd       []*PndCreateProperties `protobuf:"bytes,2,rep,name=pnd,proto3" json:"pnd,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *CreatePndListRequest) Reset() {
@@ -345,12 +340,11 @@ func (x *CreatePndListRequest) GetPnd() []*PndCreateProperties {
 }
 
 type PndCreateProperties struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Name          string                 `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+	Description   string                 `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Name        string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
-	Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *PndCreateProperties) Reset() {
@@ -398,11 +392,10 @@ func (x *PndCreateProperties) GetDescription() string {
 }
 
 type CreatePndListResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *CreatePndListResponse) Reset() {
@@ -443,12 +436,11 @@ func (x *CreatePndListResponse) GetTimestamp() int64 {
 }
 
 type DeletePndRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	Pid           string                 `protobuf:"bytes,4,opt,name=pid,proto3" json:"pid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
-	Pid       string `protobuf:"bytes,4,opt,name=pid,proto3" json:"pid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeletePndRequest) Reset() {
@@ -496,11 +488,10 @@ func (x *DeletePndRequest) GetPid() string {
 }
 
 type DeletePndResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` // Timestamp in nanoseconds since Epoch.
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeletePndResponse) Reset() {
@@ -542,7 +533,7 @@ func (x *DeletePndResponse) GetTimestamp() int64 {
 
 var File_gosdn_pnd_pnd_proto protoreflect.FileDescriptor
 
-var file_gosdn_pnd_pnd_proto_rawDesc = []byte{
+var file_gosdn_pnd_pnd_proto_rawDesc = string([]byte{
 	0x0a, 0x13, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x70, 0x6e, 0x64, 0x2f, 0x70, 0x6e, 0x64, 0x2e,
 	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x70, 0x6e, 0x64,
 	0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e,
@@ -653,16 +644,16 @@ var file_gosdn_pnd_pnd_proto_rawDesc = []byte{
 	0x2e, 0x68, 0x2d, 0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67,
 	0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64,
 	0x6e, 0x2f, 0x70, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_gosdn_pnd_pnd_proto_rawDescOnce sync.Once
-	file_gosdn_pnd_pnd_proto_rawDescData = file_gosdn_pnd_pnd_proto_rawDesc
+	file_gosdn_pnd_pnd_proto_rawDescData []byte
 )
 
 func file_gosdn_pnd_pnd_proto_rawDescGZIP() []byte {
 	file_gosdn_pnd_pnd_proto_rawDescOnce.Do(func() {
-		file_gosdn_pnd_pnd_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdn_pnd_pnd_proto_rawDescData)
+		file_gosdn_pnd_pnd_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gosdn_pnd_pnd_proto_rawDesc), len(file_gosdn_pnd_pnd_proto_rawDesc)))
 	})
 	return file_gosdn_pnd_pnd_proto_rawDescData
 }
@@ -708,7 +699,7 @@ func file_gosdn_pnd_pnd_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdn_pnd_pnd_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_gosdn_pnd_pnd_proto_rawDesc), len(file_gosdn_pnd_pnd_proto_rawDesc)),
 			NumEnums:      0,
 			NumMessages:   10,
 			NumExtensions: 0,
@@ -719,7 +710,6 @@ func file_gosdn_pnd_pnd_proto_init() {
 		MessageInfos:      file_gosdn_pnd_pnd_proto_msgTypes,
 	}.Build()
 	File_gosdn_pnd_pnd_proto = out.File
-	file_gosdn_pnd_pnd_proto_rawDesc = nil
 	file_gosdn_pnd_pnd_proto_goTypes = nil
 	file_gosdn_pnd_pnd_proto_depIdxs = nil
 }
diff --git a/api/go/gosdn/pnd/pnd.pb.gw.go b/api/go/gosdn/pnd/pnd.pb.gw.go
index 6aace9934..7ea08d765 100755
--- a/api/go/gosdn/pnd/pnd.pb.gw.go
+++ b/api/go/gosdn/pnd/pnd.pb.gw.go
@@ -10,6 +10,7 @@ package pnd
 
 import (
 	"context"
+	"errors"
 	"io"
 	"net/http"
 
@@ -24,213 +25,170 @@ import (
 )
 
 // Suppress "imported and not used" errors
-var _ codes.Code
-var _ io.Reader
-var _ status.Status
-var _ = runtime.String
-var _ = utilities.NewDoubleArray
-var _ = metadata.Join
-
 var (
-	filter_PndService_GetPnd_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
+	_ codes.Code
+	_ io.Reader
+	_ status.Status
+	_ = errors.New
+	_ = runtime.String
+	_ = utilities.NewDoubleArray
+	_ = metadata.Join
 )
 
-func request_PndService_GetPnd_0(ctx context.Context, marshaler runtime.Marshaler, client PndServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetPndRequest
-	var metadata runtime.ServerMetadata
+var filter_PndService_GetPnd_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
 
+func request_PndService_GetPnd_0(ctx context.Context, marshaler runtime.Marshaler, client PndServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq GetPndRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["pid"]
+	val, ok := pathParams["pid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "pid")
 	}
-
 	protoReq.Pid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "pid", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_PndService_GetPnd_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.GetPnd(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_PndService_GetPnd_0(ctx context.Context, marshaler runtime.Marshaler, server PndServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetPndRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq GetPndRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["pid"]
+	val, ok := pathParams["pid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "pid")
 	}
-
 	protoReq.Pid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "pid", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_PndService_GetPnd_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.GetPnd(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_PndService_GetPndList_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
-)
+var filter_PndService_GetPndList_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
 
 func request_PndService_GetPndList_0(ctx context.Context, marshaler runtime.Marshaler, client PndServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetPndListRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq GetPndListRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_PndService_GetPndList_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.GetPndList(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_PndService_GetPndList_0(ctx context.Context, marshaler runtime.Marshaler, server PndServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetPndListRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq GetPndListRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_PndService_GetPndList_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.GetPndList(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 func request_PndService_CreatePndList_0(ctx context.Context, marshaler runtime.Marshaler, client PndServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq CreatePndListRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq CreatePndListRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.CreatePndList(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_PndService_CreatePndList_0(ctx context.Context, marshaler runtime.Marshaler, server PndServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq CreatePndListRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq CreatePndListRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.CreatePndList(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_PndService_DeletePnd_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
-)
+var filter_PndService_DeletePnd_0 = &utilities.DoubleArray{Encoding: map[string]int{"pid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
 
 func request_PndService_DeletePnd_0(ctx context.Context, marshaler runtime.Marshaler, client PndServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeletePndRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq DeletePndRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["pid"]
+	val, ok := pathParams["pid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "pid")
 	}
-
 	protoReq.Pid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "pid", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_PndService_DeletePnd_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.DeletePnd(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_PndService_DeletePnd_0(ctx context.Context, marshaler runtime.Marshaler, server PndServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeletePndRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq DeletePndRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["pid"]
+	val, ok := pathParams["pid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "pid")
 	}
-
 	protoReq.Pid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "pid", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_PndService_DeletePnd_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.DeletePnd(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 // RegisterPndServiceHandlerServer registers the http handlers for service PndService to "mux".
@@ -239,16 +197,13 @@ func local_request_PndService_DeletePnd_0(ctx context.Context, marshaler runtime
 // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterPndServiceHandlerFromEndpoint instead.
 // GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
 func RegisterPndServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server PndServiceServer) error {
-
-	mux.Handle("GET", pattern_PndService_GetPnd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_PndService_GetPnd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.pnd.PndService/GetPnd", runtime.WithHTTPPathPattern("/pnd/{pid}"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.pnd.PndService/GetPnd", runtime.WithHTTPPathPattern("/pnd/{pid}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -260,20 +215,15 @@ func RegisterPndServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux,
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_PndService_GetPnd_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_PndService_GetPndList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_PndService_GetPndList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.pnd.PndService/GetPndList", runtime.WithHTTPPathPattern("/pnds"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.pnd.PndService/GetPndList", runtime.WithHTTPPathPattern("/pnds"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -285,20 +235,15 @@ func RegisterPndServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux,
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_PndService_GetPndList_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_PndService_CreatePndList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_PndService_CreatePndList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.pnd.PndService/CreatePndList", runtime.WithHTTPPathPattern("/pnds"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.pnd.PndService/CreatePndList", runtime.WithHTTPPathPattern("/pnds"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -310,20 +255,15 @@ func RegisterPndServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux,
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_PndService_CreatePndList_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_PndService_DeletePnd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_PndService_DeletePnd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.pnd.PndService/DeletePnd", runtime.WithHTTPPathPattern("/pnds/{pid}"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.pnd.PndService/DeletePnd", runtime.WithHTTPPathPattern("/pnds/{pid}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -335,9 +275,7 @@ func RegisterPndServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux,
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_PndService_DeletePnd_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
 
 	return nil
@@ -364,7 +302,6 @@ func RegisterPndServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.Ser
 			}
 		}()
 	}()
-
 	return RegisterPndServiceHandler(ctx, mux, conn)
 }
 
@@ -380,14 +317,11 @@ func RegisterPndServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn
 // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
 // "PndServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares.
 func RegisterPndServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client PndServiceClient) error {
-
-	mux.Handle("GET", pattern_PndService_GetPnd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_PndService_GetPnd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.pnd.PndService/GetPnd", runtime.WithHTTPPathPattern("/pnd/{pid}"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.pnd.PndService/GetPnd", runtime.WithHTTPPathPattern("/pnd/{pid}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -398,18 +332,13 @@ func RegisterPndServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux,
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_PndService_GetPnd_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_PndService_GetPndList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_PndService_GetPndList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.pnd.PndService/GetPndList", runtime.WithHTTPPathPattern("/pnds"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.pnd.PndService/GetPndList", runtime.WithHTTPPathPattern("/pnds"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -420,18 +349,13 @@ func RegisterPndServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux,
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_PndService_GetPndList_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_PndService_CreatePndList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_PndService_CreatePndList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.pnd.PndService/CreatePndList", runtime.WithHTTPPathPattern("/pnds"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.pnd.PndService/CreatePndList", runtime.WithHTTPPathPattern("/pnds"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -442,18 +366,13 @@ func RegisterPndServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux,
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_PndService_CreatePndList_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_PndService_DeletePnd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_PndService_DeletePnd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.pnd.PndService/DeletePnd", runtime.WithHTTPPathPattern("/pnds/{pid}"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.pnd.PndService/DeletePnd", runtime.WithHTTPPathPattern("/pnds/{pid}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -464,30 +383,21 @@ func RegisterPndServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux,
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_PndService_DeletePnd_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
 	return nil
 }
 
 var (
-	pattern_PndService_GetPnd_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"pnd", "pid"}, ""))
-
-	pattern_PndService_GetPndList_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"pnds"}, ""))
-
+	pattern_PndService_GetPnd_0        = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"pnd", "pid"}, ""))
+	pattern_PndService_GetPndList_0    = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"pnds"}, ""))
 	pattern_PndService_CreatePndList_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"pnds"}, ""))
-
-	pattern_PndService_DeletePnd_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"pnds", "pid"}, ""))
+	pattern_PndService_DeletePnd_0     = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"pnds", "pid"}, ""))
 )
 
 var (
-	forward_PndService_GetPnd_0 = runtime.ForwardResponseMessage
-
-	forward_PndService_GetPndList_0 = runtime.ForwardResponseMessage
-
+	forward_PndService_GetPnd_0        = runtime.ForwardResponseMessage
+	forward_PndService_GetPndList_0    = runtime.ForwardResponseMessage
 	forward_PndService_CreatePndList_0 = runtime.ForwardResponseMessage
-
-	forward_PndService_DeletePnd_0 = runtime.ForwardResponseMessage
+	forward_PndService_DeletePnd_0     = runtime.ForwardResponseMessage
 )
diff --git a/api/go/gosdn/rbac/rbac.pb.go b/api/go/gosdn/rbac/rbac.pb.go
index 0a98e9ecf..29e570c59 100755
--- a/api/go/gosdn/rbac/rbac.pb.go
+++ b/api/go/gosdn/rbac/rbac.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: gosdn/rbac/rbac.proto
 
@@ -15,6 +15,7 @@ import (
 	_ "google.golang.org/protobuf/types/descriptorpb"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -26,13 +27,12 @@ const (
 
 // Login
 type LoginRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Username      string                 `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
+	Pwd           string                 `protobuf:"bytes,3,opt,name=pwd,proto3" json:"pwd,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Username  string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
-	Pwd       string `protobuf:"bytes,3,opt,name=pwd,proto3" json:"pwd,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *LoginRequest) Reset() {
@@ -87,12 +87,11 @@ func (x *LoginRequest) GetPwd() string {
 }
 
 type LoginResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Token         string                 `protobuf:"bytes,2,opt,name=token,proto3" json:"token,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Token     string `protobuf:"bytes,2,opt,name=token,proto3" json:"token,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *LoginResponse) Reset() {
@@ -141,12 +140,11 @@ func (x *LoginResponse) GetToken() string {
 
 // Logout
 type LogoutRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Username      string                 `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Username  string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *LogoutRequest) Reset() {
@@ -194,11 +192,10 @@ func (x *LogoutRequest) GetUsername() string {
 }
 
 type LogoutResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *LogoutResponse) Reset() {
@@ -240,7 +237,7 @@ func (x *LogoutResponse) GetTimestamp() int64 {
 
 var File_gosdn_rbac_rbac_proto protoreflect.FileDescriptor
 
-var file_gosdn_rbac_rbac_proto_rawDesc = []byte{
+var file_gosdn_rbac_rbac_proto_rawDesc = string([]byte{
 	0x0a, 0x15, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x72, 0x62, 0x61, 0x63, 0x2f, 0x72, 0x62, 0x61,
 	0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x72,
 	0x62, 0x61, 0x63, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f,
@@ -287,16 +284,16 @@ var file_gosdn_rbac_rbac_proto_rawDesc = []byte{
 	0x2d, 0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67, 0x6f, 0x73,
 	0x64, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f,
 	0x72, 0x62, 0x61, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_gosdn_rbac_rbac_proto_rawDescOnce sync.Once
-	file_gosdn_rbac_rbac_proto_rawDescData = file_gosdn_rbac_rbac_proto_rawDesc
+	file_gosdn_rbac_rbac_proto_rawDescData []byte
 )
 
 func file_gosdn_rbac_rbac_proto_rawDescGZIP() []byte {
 	file_gosdn_rbac_rbac_proto_rawDescOnce.Do(func() {
-		file_gosdn_rbac_rbac_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdn_rbac_rbac_proto_rawDescData)
+		file_gosdn_rbac_rbac_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gosdn_rbac_rbac_proto_rawDesc), len(file_gosdn_rbac_rbac_proto_rawDesc)))
 	})
 	return file_gosdn_rbac_rbac_proto_rawDescData
 }
@@ -329,7 +326,7 @@ func file_gosdn_rbac_rbac_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdn_rbac_rbac_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_gosdn_rbac_rbac_proto_rawDesc), len(file_gosdn_rbac_rbac_proto_rawDesc)),
 			NumEnums:      0,
 			NumMessages:   4,
 			NumExtensions: 0,
@@ -340,7 +337,6 @@ func file_gosdn_rbac_rbac_proto_init() {
 		MessageInfos:      file_gosdn_rbac_rbac_proto_msgTypes,
 	}.Build()
 	File_gosdn_rbac_rbac_proto = out.File
-	file_gosdn_rbac_rbac_proto_rawDesc = nil
 	file_gosdn_rbac_rbac_proto_goTypes = nil
 	file_gosdn_rbac_rbac_proto_depIdxs = nil
 }
diff --git a/api/go/gosdn/rbac/rbac.pb.gw.go b/api/go/gosdn/rbac/rbac.pb.gw.go
index 46167531e..6a89867f0 100755
--- a/api/go/gosdn/rbac/rbac.pb.gw.go
+++ b/api/go/gosdn/rbac/rbac.pb.gw.go
@@ -10,6 +10,7 @@ package rbac
 
 import (
 	"context"
+	"errors"
 	"io"
 	"net/http"
 
@@ -24,107 +25,88 @@ import (
 )
 
 // Suppress "imported and not used" errors
-var _ codes.Code
-var _ io.Reader
-var _ status.Status
-var _ = runtime.String
-var _ = utilities.NewDoubleArray
-var _ = metadata.Join
+var (
+	_ codes.Code
+	_ io.Reader
+	_ status.Status
+	_ = errors.New
+	_ = runtime.String
+	_ = utilities.NewDoubleArray
+	_ = metadata.Join
+)
 
 func request_AuthService_Login_0(ctx context.Context, marshaler runtime.Marshaler, client AuthServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq LoginRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq LoginRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.Login(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_AuthService_Login_0(ctx context.Context, marshaler runtime.Marshaler, server AuthServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq LoginRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq LoginRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.Login(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_AuthService_Logout_0 = &utilities.DoubleArray{Encoding: map[string]int{"username": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
-)
+var filter_AuthService_Logout_0 = &utilities.DoubleArray{Encoding: map[string]int{"username": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
 
 func request_AuthService_Logout_0(ctx context.Context, marshaler runtime.Marshaler, client AuthServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq LogoutRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq LogoutRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["username"]
+	val, ok := pathParams["username"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "username")
 	}
-
 	protoReq.Username, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "username", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_AuthService_Logout_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.Logout(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_AuthService_Logout_0(ctx context.Context, marshaler runtime.Marshaler, server AuthServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq LogoutRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq LogoutRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["username"]
+	val, ok := pathParams["username"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "username")
 	}
-
 	protoReq.Username, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "username", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_AuthService_Logout_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.Logout(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 // RegisterAuthServiceHandlerServer registers the http handlers for service AuthService to "mux".
@@ -133,16 +115,13 @@ func local_request_AuthService_Logout_0(ctx context.Context, marshaler runtime.M
 // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterAuthServiceHandlerFromEndpoint instead.
 // GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
 func RegisterAuthServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server AuthServiceServer) error {
-
-	mux.Handle("POST", pattern_AuthService_Login_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_AuthService_Login_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.AuthService/Login", runtime.WithHTTPPathPattern("/login"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.AuthService/Login", runtime.WithHTTPPathPattern("/login"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -154,20 +133,15 @@ func RegisterAuthServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_AuthService_Login_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_AuthService_Logout_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_AuthService_Logout_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.AuthService/Logout", runtime.WithHTTPPathPattern("/logout/{username}"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.AuthService/Logout", runtime.WithHTTPPathPattern("/logout/{username}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -179,9 +153,7 @@ func RegisterAuthServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_AuthService_Logout_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
 
 	return nil
@@ -208,7 +180,6 @@ func RegisterAuthServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.Se
 			}
 		}()
 	}()
-
 	return RegisterAuthServiceHandler(ctx, mux, conn)
 }
 
@@ -224,14 +195,11 @@ func RegisterAuthServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn
 // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
 // "AuthServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares.
 func RegisterAuthServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client AuthServiceClient) error {
-
-	mux.Handle("POST", pattern_AuthService_Login_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_AuthService_Login_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.AuthService/Login", runtime.WithHTTPPathPattern("/login"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.AuthService/Login", runtime.WithHTTPPathPattern("/login"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -242,18 +210,13 @@ func RegisterAuthServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_AuthService_Login_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_AuthService_Logout_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_AuthService_Logout_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.AuthService/Logout", runtime.WithHTTPPathPattern("/logout/{username}"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.AuthService/Logout", runtime.WithHTTPPathPattern("/logout/{username}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -264,22 +227,17 @@ func RegisterAuthServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_AuthService_Logout_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
 	return nil
 }
 
 var (
-	pattern_AuthService_Login_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"login"}, ""))
-
+	pattern_AuthService_Login_0  = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"login"}, ""))
 	pattern_AuthService_Logout_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"logout", "username"}, ""))
 )
 
 var (
-	forward_AuthService_Login_0 = runtime.ForwardResponseMessage
-
+	forward_AuthService_Login_0  = runtime.ForwardResponseMessage
 	forward_AuthService_Logout_0 = runtime.ForwardResponseMessage
 )
diff --git a/api/go/gosdn/rbac/role.pb.go b/api/go/gosdn/rbac/role.pb.go
index aacf29035..66c89c2f7 100755
--- a/api/go/gosdn/rbac/role.pb.go
+++ b/api/go/gosdn/rbac/role.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: gosdn/rbac/role.proto
 
@@ -15,6 +15,7 @@ import (
 	_ "google.golang.org/protobuf/types/descriptorpb"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -25,14 +26,13 @@ const (
 )
 
 type Role struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Id            string                 `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	Name          string                 `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+	Description   string                 `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
+	Permissions   []string               `protobuf:"bytes,4,rep,name=permissions,proto3" json:"permissions,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Id          string   `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	Name        string   `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
-	Description string   `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
-	Permissions []string `protobuf:"bytes,4,rep,name=permissions,proto3" json:"permissions,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Role) Reset() {
@@ -95,12 +95,11 @@ func (x *Role) GetPermissions() []string {
 
 // CreateRoles
 type CreateRolesRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Roles         []*Role                `protobuf:"bytes,2,rep,name=roles,proto3" json:"roles,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64   `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Roles     []*Role `protobuf:"bytes,2,rep,name=roles,proto3" json:"roles,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *CreateRolesRequest) Reset() {
@@ -148,11 +147,10 @@ func (x *CreateRolesRequest) GetRoles() []*Role {
 }
 
 type CreateRolesResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *CreateRolesResponse) Reset() {
@@ -194,13 +192,12 @@ func (x *CreateRolesResponse) GetTimestamp() int64 {
 
 // GetRole
 type GetRoleRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	RoleName      string                 `protobuf:"bytes,2,opt,name=role_name,json=roleName,proto3" json:"role_name,omitempty"`
+	Id            string                 `protobuf:"bytes,3,opt,name=id,proto3" json:"id,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	RoleName  string `protobuf:"bytes,2,opt,name=role_name,json=roleName,proto3" json:"role_name,omitempty"`
-	Id        string `protobuf:"bytes,3,opt,name=id,proto3" json:"id,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetRoleRequest) Reset() {
@@ -255,12 +252,11 @@ func (x *GetRoleRequest) GetId() string {
 }
 
 type GetRoleResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Role          *Role                  `protobuf:"bytes,2,opt,name=role,proto3" json:"role,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Role      *Role `protobuf:"bytes,2,opt,name=role,proto3" json:"role,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetRoleResponse) Reset() {
@@ -309,11 +305,10 @@ func (x *GetRoleResponse) GetRole() *Role {
 
 // GetRoles
 type GetRolesRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetRolesRequest) Reset() {
@@ -354,12 +349,11 @@ func (x *GetRolesRequest) GetTimestamp() int64 {
 }
 
 type GetRolesResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Roles         []*Role                `protobuf:"bytes,2,rep,name=roles,proto3" json:"roles,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64   `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Roles     []*Role `protobuf:"bytes,2,rep,name=roles,proto3" json:"roles,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetRolesResponse) Reset() {
@@ -408,12 +402,11 @@ func (x *GetRolesResponse) GetRoles() []*Role {
 
 // UpdateRoles
 type UpdateRolesRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Roles         []*Role                `protobuf:"bytes,2,rep,name=roles,proto3" json:"roles,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64   `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Roles     []*Role `protobuf:"bytes,2,rep,name=roles,proto3" json:"roles,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *UpdateRolesRequest) Reset() {
@@ -461,11 +454,10 @@ func (x *UpdateRolesRequest) GetRoles() []*Role {
 }
 
 type UpdateRolesResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *UpdateRolesResponse) Reset() {
@@ -507,13 +499,12 @@ func (x *UpdateRolesResponse) GetTimestamp() int64 {
 
 // DeletePermissionsForRole
 type DeletePermissionsForRoleRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Timestamp           int64    `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	RoleName            string   `protobuf:"bytes,2,opt,name=role_name,json=roleName,proto3" json:"role_name,omitempty"`
-	PermissionsToDelete []string `protobuf:"bytes,3,rep,name=permissions_to_delete,json=permissionsToDelete,proto3" json:"permissions_to_delete,omitempty"`
+	state               protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp           int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	RoleName            string                 `protobuf:"bytes,2,opt,name=role_name,json=roleName,proto3" json:"role_name,omitempty"`
+	PermissionsToDelete []string               `protobuf:"bytes,3,rep,name=permissions_to_delete,json=permissionsToDelete,proto3" json:"permissions_to_delete,omitempty"`
+	unknownFields       protoimpl.UnknownFields
+	sizeCache           protoimpl.SizeCache
 }
 
 func (x *DeletePermissionsForRoleRequest) Reset() {
@@ -568,11 +559,10 @@ func (x *DeletePermissionsForRoleRequest) GetPermissionsToDelete() []string {
 }
 
 type DeletePermissionsForRoleResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeletePermissionsForRoleResponse) Reset() {
@@ -614,12 +604,11 @@ func (x *DeletePermissionsForRoleResponse) GetTimestamp() int64 {
 
 // DeleteRoles
 type DeleteRolesRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	RoleName      []string               `protobuf:"bytes,2,rep,name=role_name,json=roleName,proto3" json:"role_name,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64    `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	RoleName  []string `protobuf:"bytes,2,rep,name=role_name,json=roleName,proto3" json:"role_name,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeleteRolesRequest) Reset() {
@@ -667,11 +656,10 @@ func (x *DeleteRolesRequest) GetRoleName() []string {
 }
 
 type DeleteRolesResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeleteRolesResponse) Reset() {
@@ -713,7 +701,7 @@ func (x *DeleteRolesResponse) GetTimestamp() int64 {
 
 var File_gosdn_rbac_role_proto protoreflect.FileDescriptor
 
-var file_gosdn_rbac_role_proto_rawDesc = []byte{
+var file_gosdn_rbac_role_proto_rawDesc = string([]byte{
 	0x0a, 0x15, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x72, 0x62, 0x61, 0x63, 0x2f, 0x72, 0x6f, 0x6c,
 	0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x72,
 	0x62, 0x61, 0x63, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f,
@@ -842,16 +830,16 @@ var file_gosdn_rbac_role_proto_rawDesc = []byte{
 	0x68, 0x2d, 0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67, 0x6f,
 	0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e,
 	0x2f, 0x72, 0x62, 0x61, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_gosdn_rbac_role_proto_rawDescOnce sync.Once
-	file_gosdn_rbac_role_proto_rawDescData = file_gosdn_rbac_role_proto_rawDesc
+	file_gosdn_rbac_role_proto_rawDescData []byte
 )
 
 func file_gosdn_rbac_role_proto_rawDescGZIP() []byte {
 	file_gosdn_rbac_role_proto_rawDescOnce.Do(func() {
-		file_gosdn_rbac_role_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdn_rbac_role_proto_rawDescData)
+		file_gosdn_rbac_role_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gosdn_rbac_role_proto_rawDesc), len(file_gosdn_rbac_role_proto_rawDesc)))
 	})
 	return file_gosdn_rbac_role_proto_rawDescData
 }
@@ -906,7 +894,7 @@ func file_gosdn_rbac_role_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdn_rbac_role_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_gosdn_rbac_role_proto_rawDesc), len(file_gosdn_rbac_role_proto_rawDesc)),
 			NumEnums:      0,
 			NumMessages:   13,
 			NumExtensions: 0,
@@ -917,7 +905,6 @@ func file_gosdn_rbac_role_proto_init() {
 		MessageInfos:      file_gosdn_rbac_role_proto_msgTypes,
 	}.Build()
 	File_gosdn_rbac_role_proto = out.File
-	file_gosdn_rbac_role_proto_rawDesc = nil
 	file_gosdn_rbac_role_proto_goTypes = nil
 	file_gosdn_rbac_role_proto_depIdxs = nil
 }
diff --git a/api/go/gosdn/rbac/role.pb.gw.go b/api/go/gosdn/rbac/role.pb.gw.go
index 454fe45f0..a30fb131d 100755
--- a/api/go/gosdn/rbac/role.pb.gw.go
+++ b/api/go/gosdn/rbac/role.pb.gw.go
@@ -10,6 +10,7 @@ package rbac
 
 import (
 	"context"
+	"errors"
 	"io"
 	"net/http"
 
@@ -24,207 +25,190 @@ import (
 )
 
 // Suppress "imported and not used" errors
-var _ codes.Code
-var _ io.Reader
-var _ status.Status
-var _ = runtime.String
-var _ = utilities.NewDoubleArray
-var _ = metadata.Join
+var (
+	_ codes.Code
+	_ io.Reader
+	_ status.Status
+	_ = errors.New
+	_ = runtime.String
+	_ = utilities.NewDoubleArray
+	_ = metadata.Join
+)
 
 func request_RoleService_CreateRoles_0(ctx context.Context, marshaler runtime.Marshaler, client RoleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq CreateRolesRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq CreateRolesRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.CreateRoles(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_RoleService_CreateRoles_0(ctx context.Context, marshaler runtime.Marshaler, server RoleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq CreateRolesRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq CreateRolesRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.CreateRoles(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_RoleService_GetRole_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
-)
+var filter_RoleService_GetRole_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
 
 func request_RoleService_GetRole_0(ctx context.Context, marshaler runtime.Marshaler, client RoleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetRoleRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq GetRoleRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_RoleService_GetRole_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.GetRole(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_RoleService_GetRole_0(ctx context.Context, marshaler runtime.Marshaler, server RoleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetRoleRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq GetRoleRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_RoleService_GetRole_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.GetRole(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_RoleService_GetRoles_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
-)
+var filter_RoleService_GetRoles_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
 
 func request_RoleService_GetRoles_0(ctx context.Context, marshaler runtime.Marshaler, client RoleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetRolesRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq GetRolesRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_RoleService_GetRoles_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.GetRoles(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_RoleService_GetRoles_0(ctx context.Context, marshaler runtime.Marshaler, server RoleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetRolesRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq GetRolesRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_RoleService_GetRoles_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.GetRoles(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 func request_RoleService_UpdateRoles_0(ctx context.Context, marshaler runtime.Marshaler, client RoleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq UpdateRolesRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq UpdateRolesRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.UpdateRoles(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_RoleService_UpdateRoles_0(ctx context.Context, marshaler runtime.Marshaler, server RoleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq UpdateRolesRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq UpdateRolesRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.UpdateRoles(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_RoleService_DeletePermissionsForRole_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
-)
+var filter_RoleService_DeletePermissionsForRole_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
 
 func request_RoleService_DeletePermissionsForRole_0(ctx context.Context, marshaler runtime.Marshaler, client RoleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeletePermissionsForRoleRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq DeletePermissionsForRoleRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_RoleService_DeletePermissionsForRole_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.DeletePermissionsForRole(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_RoleService_DeletePermissionsForRole_0(ctx context.Context, marshaler runtime.Marshaler, server RoleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeletePermissionsForRoleRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq DeletePermissionsForRoleRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_RoleService_DeletePermissionsForRole_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.DeletePermissionsForRole(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_RoleService_DeleteRoles_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
-)
+var filter_RoleService_DeleteRoles_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
 
 func request_RoleService_DeleteRoles_0(ctx context.Context, marshaler runtime.Marshaler, client RoleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeleteRolesRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq DeleteRolesRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_RoleService_DeleteRoles_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.DeleteRoles(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_RoleService_DeleteRoles_0(ctx context.Context, marshaler runtime.Marshaler, server RoleServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeleteRolesRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq DeleteRolesRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_RoleService_DeleteRoles_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.DeleteRoles(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 // RegisterRoleServiceHandlerServer registers the http handlers for service RoleService to "mux".
@@ -233,16 +217,13 @@ func local_request_RoleService_DeleteRoles_0(ctx context.Context, marshaler runt
 // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterRoleServiceHandlerFromEndpoint instead.
 // GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
 func RegisterRoleServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server RoleServiceServer) error {
-
-	mux.Handle("POST", pattern_RoleService_CreateRoles_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_RoleService_CreateRoles_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.RoleService/CreateRoles", runtime.WithHTTPPathPattern("/roles/create"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.RoleService/CreateRoles", runtime.WithHTTPPathPattern("/roles/create"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -254,20 +235,15 @@ func RegisterRoleServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RoleService_CreateRoles_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_RoleService_GetRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_RoleService_GetRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.RoleService/GetRole", runtime.WithHTTPPathPattern("/roles/get"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.RoleService/GetRole", runtime.WithHTTPPathPattern("/roles/get"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -279,20 +255,15 @@ func RegisterRoleServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RoleService_GetRole_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_RoleService_GetRoles_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_RoleService_GetRoles_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.RoleService/GetRoles", runtime.WithHTTPPathPattern("/roles"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.RoleService/GetRoles", runtime.WithHTTPPathPattern("/roles"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -304,20 +275,15 @@ func RegisterRoleServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RoleService_GetRoles_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_RoleService_UpdateRoles_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_RoleService_UpdateRoles_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.RoleService/UpdateRoles", runtime.WithHTTPPathPattern("/roles/update"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.RoleService/UpdateRoles", runtime.WithHTTPPathPattern("/roles/update"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -329,20 +295,15 @@ func RegisterRoleServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RoleService_UpdateRoles_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_RoleService_DeletePermissionsForRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_RoleService_DeletePermissionsForRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.RoleService/DeletePermissionsForRole", runtime.WithHTTPPathPattern("/roles/delete/permissions"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.RoleService/DeletePermissionsForRole", runtime.WithHTTPPathPattern("/roles/delete/permissions"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -354,20 +315,15 @@ func RegisterRoleServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RoleService_DeletePermissionsForRole_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_RoleService_DeleteRoles_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_RoleService_DeleteRoles_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.RoleService/DeleteRoles", runtime.WithHTTPPathPattern("/roles/delete"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.RoleService/DeleteRoles", runtime.WithHTTPPathPattern("/roles/delete"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -379,9 +335,7 @@ func RegisterRoleServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RoleService_DeleteRoles_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
 
 	return nil
@@ -408,7 +362,6 @@ func RegisterRoleServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.Se
 			}
 		}()
 	}()
-
 	return RegisterRoleServiceHandler(ctx, mux, conn)
 }
 
@@ -424,14 +377,11 @@ func RegisterRoleServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn
 // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
 // "RoleServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares.
 func RegisterRoleServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client RoleServiceClient) error {
-
-	mux.Handle("POST", pattern_RoleService_CreateRoles_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_RoleService_CreateRoles_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.RoleService/CreateRoles", runtime.WithHTTPPathPattern("/roles/create"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.RoleService/CreateRoles", runtime.WithHTTPPathPattern("/roles/create"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -442,18 +392,13 @@ func RegisterRoleServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RoleService_CreateRoles_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_RoleService_GetRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_RoleService_GetRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.RoleService/GetRole", runtime.WithHTTPPathPattern("/roles/get"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.RoleService/GetRole", runtime.WithHTTPPathPattern("/roles/get"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -464,18 +409,13 @@ func RegisterRoleServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RoleService_GetRole_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_RoleService_GetRoles_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_RoleService_GetRoles_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.RoleService/GetRoles", runtime.WithHTTPPathPattern("/roles"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.RoleService/GetRoles", runtime.WithHTTPPathPattern("/roles"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -486,18 +426,13 @@ func RegisterRoleServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RoleService_GetRoles_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_RoleService_UpdateRoles_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_RoleService_UpdateRoles_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.RoleService/UpdateRoles", runtime.WithHTTPPathPattern("/roles/update"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.RoleService/UpdateRoles", runtime.WithHTTPPathPattern("/roles/update"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -508,18 +443,13 @@ func RegisterRoleServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RoleService_UpdateRoles_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_RoleService_DeletePermissionsForRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_RoleService_DeletePermissionsForRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.RoleService/DeletePermissionsForRole", runtime.WithHTTPPathPattern("/roles/delete/permissions"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.RoleService/DeletePermissionsForRole", runtime.WithHTTPPathPattern("/roles/delete/permissions"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -530,18 +460,13 @@ func RegisterRoleServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RoleService_DeletePermissionsForRole_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_RoleService_DeleteRoles_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_RoleService_DeleteRoles_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.RoleService/DeleteRoles", runtime.WithHTTPPathPattern("/roles/delete"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.RoleService/DeleteRoles", runtime.WithHTTPPathPattern("/roles/delete"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -552,38 +477,25 @@ func RegisterRoleServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RoleService_DeleteRoles_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
 	return nil
 }
 
 var (
-	pattern_RoleService_CreateRoles_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"roles", "create"}, ""))
-
-	pattern_RoleService_GetRole_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"roles", "get"}, ""))
-
-	pattern_RoleService_GetRoles_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"roles"}, ""))
-
-	pattern_RoleService_UpdateRoles_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"roles", "update"}, ""))
-
+	pattern_RoleService_CreateRoles_0              = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"roles", "create"}, ""))
+	pattern_RoleService_GetRole_0                  = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"roles", "get"}, ""))
+	pattern_RoleService_GetRoles_0                 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"roles"}, ""))
+	pattern_RoleService_UpdateRoles_0              = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"roles", "update"}, ""))
 	pattern_RoleService_DeletePermissionsForRole_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"roles", "delete", "permissions"}, ""))
-
-	pattern_RoleService_DeleteRoles_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"roles", "delete"}, ""))
+	pattern_RoleService_DeleteRoles_0              = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"roles", "delete"}, ""))
 )
 
 var (
-	forward_RoleService_CreateRoles_0 = runtime.ForwardResponseMessage
-
-	forward_RoleService_GetRole_0 = runtime.ForwardResponseMessage
-
-	forward_RoleService_GetRoles_0 = runtime.ForwardResponseMessage
-
-	forward_RoleService_UpdateRoles_0 = runtime.ForwardResponseMessage
-
+	forward_RoleService_CreateRoles_0              = runtime.ForwardResponseMessage
+	forward_RoleService_GetRole_0                  = runtime.ForwardResponseMessage
+	forward_RoleService_GetRoles_0                 = runtime.ForwardResponseMessage
+	forward_RoleService_UpdateRoles_0              = runtime.ForwardResponseMessage
 	forward_RoleService_DeletePermissionsForRole_0 = runtime.ForwardResponseMessage
-
-	forward_RoleService_DeleteRoles_0 = runtime.ForwardResponseMessage
+	forward_RoleService_DeleteRoles_0              = runtime.ForwardResponseMessage
 )
diff --git a/api/go/gosdn/rbac/user.pb.go b/api/go/gosdn/rbac/user.pb.go
index 6c5c74f57..6c413ce8c 100755
--- a/api/go/gosdn/rbac/user.pb.go
+++ b/api/go/gosdn/rbac/user.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: gosdn/rbac/user.proto
 
@@ -16,6 +16,7 @@ import (
 	_ "google.golang.org/protobuf/types/descriptorpb"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -26,16 +27,15 @@ const (
 )
 
 type User struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Id            string                 `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	Name          string                 `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+	Roles         map[string]string      `protobuf:"bytes,3,rep,name=roles,proto3" json:"roles,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // Key = pnd uuid, value= role name
+	Password      string                 `protobuf:"bytes,4,opt,name=password,proto3" json:"password,omitempty"`
+	Token         string                 `protobuf:"bytes,5,opt,name=token,proto3" json:"token,omitempty"`
+	Metadata      *conflict.Metadata     `protobuf:"bytes,6,opt,name=metadata,proto3" json:"metadata,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Id       string             `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	Name     string             `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
-	Roles    map[string]string  `protobuf:"bytes,3,rep,name=roles,proto3" json:"roles,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // Key = pnd uuid, value= role name
-	Password string             `protobuf:"bytes,4,opt,name=password,proto3" json:"password,omitempty"`
-	Token    string             `protobuf:"bytes,5,opt,name=token,proto3" json:"token,omitempty"`
-	Metadata *conflict.Metadata `protobuf:"bytes,6,opt,name=metadata,proto3" json:"metadata,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *User) Reset() {
@@ -111,16 +111,15 @@ func (x *User) GetMetadata() *conflict.Metadata {
 }
 
 type UpdateUser struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Id            string                 `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	Name          string                 `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+	Roles         map[string]string      `protobuf:"bytes,3,rep,name=roles,proto3" json:"roles,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // Key = pnd uuid, value= role name
+	Password      string                 `protobuf:"bytes,4,opt,name=password,proto3" json:"password,omitempty"`
+	Token         string                 `protobuf:"bytes,5,opt,name=token,proto3" json:"token,omitempty"`
+	Metadata      *conflict.Metadata     `protobuf:"bytes,6,opt,name=metadata,proto3" json:"metadata,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Id       string             `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	Name     string             `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
-	Roles    map[string]string  `protobuf:"bytes,3,rep,name=roles,proto3" json:"roles,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // Key = pnd uuid, value= role name
-	Password string             `protobuf:"bytes,4,opt,name=password,proto3" json:"password,omitempty"`
-	Token    string             `protobuf:"bytes,5,opt,name=token,proto3" json:"token,omitempty"`
-	Metadata *conflict.Metadata `protobuf:"bytes,6,opt,name=metadata,proto3" json:"metadata,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *UpdateUser) Reset() {
@@ -197,12 +196,11 @@ func (x *UpdateUser) GetMetadata() *conflict.Metadata {
 
 // CreateUsers
 type CreateUsersRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	User          []*User                `protobuf:"bytes,2,rep,name=user,proto3" json:"user,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64   `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	User      []*User `protobuf:"bytes,2,rep,name=user,proto3" json:"user,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *CreateUsersRequest) Reset() {
@@ -250,11 +248,10 @@ func (x *CreateUsersRequest) GetUser() []*User {
 }
 
 type CreateUsersResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *CreateUsersResponse) Reset() {
@@ -296,13 +293,12 @@ func (x *CreateUsersResponse) GetTimestamp() int64 {
 
 // GetUser
 type GetUserRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Name          string                 `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` // TODO(faseid): reconsider if this is necessary as required, but id is not?
+	Id            string                 `protobuf:"bytes,3,opt,name=id,proto3" json:"id,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Name      string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` // TODO(faseid): reconsider if this is necessary as required, but id is not?
-	Id        string `protobuf:"bytes,3,opt,name=id,proto3" json:"id,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetUserRequest) Reset() {
@@ -357,12 +353,11 @@ func (x *GetUserRequest) GetId() string {
 }
 
 type GetUserResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	User          *User                  `protobuf:"bytes,2,opt,name=user,proto3" json:"user,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	User      *User `protobuf:"bytes,2,opt,name=user,proto3" json:"user,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetUserResponse) Reset() {
@@ -411,11 +406,10 @@ func (x *GetUserResponse) GetUser() *User {
 
 // GetUsers
 type GetUsersRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetUsersRequest) Reset() {
@@ -456,12 +450,11 @@ func (x *GetUsersRequest) GetTimestamp() int64 {
 }
 
 type GetUsersResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	User          []*User                `protobuf:"bytes,2,rep,name=user,proto3" json:"user,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64   `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	User      []*User `protobuf:"bytes,2,rep,name=user,proto3" json:"user,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetUsersResponse) Reset() {
@@ -510,12 +503,11 @@ func (x *GetUsersResponse) GetUser() []*User {
 
 // UpdateUsers
 type UpdateUsersRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	User          []*UpdateUser          `protobuf:"bytes,2,rep,name=user,proto3" json:"user,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64         `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	User      []*UpdateUser `protobuf:"bytes,2,rep,name=user,proto3" json:"user,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *UpdateUsersRequest) Reset() {
@@ -563,11 +555,10 @@ func (x *UpdateUsersRequest) GetUser() []*UpdateUser {
 }
 
 type UpdateUsersResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *UpdateUsersResponse) Reset() {
@@ -609,12 +600,11 @@ func (x *UpdateUsersResponse) GetTimestamp() int64 {
 
 // DeleteUsers
 type DeleteUsersRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Username      []string               `protobuf:"bytes,2,rep,name=username,proto3" json:"username,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64    `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Username  []string `protobuf:"bytes,2,rep,name=username,proto3" json:"username,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeleteUsersRequest) Reset() {
@@ -662,11 +652,10 @@ func (x *DeleteUsersRequest) GetUsername() []string {
 }
 
 type DeleteUsersResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeleteUsersResponse) Reset() {
@@ -708,7 +697,7 @@ func (x *DeleteUsersResponse) GetTimestamp() int64 {
 
 var File_gosdn_rbac_user_proto protoreflect.FileDescriptor
 
-var file_gosdn_rbac_user_proto_rawDesc = []byte{
+var file_gosdn_rbac_user_proto_rawDesc = string([]byte{
 	0x0a, 0x15, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x72, 0x62, 0x61, 0x63, 0x2f, 0x75, 0x73, 0x65,
 	0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x72,
 	0x62, 0x61, 0x63, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f,
@@ -841,16 +830,16 @@ var file_gosdn_rbac_user_proto_rawDesc = []byte{
 	0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f,
 	0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x72, 0x62, 0x61,
 	0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_gosdn_rbac_user_proto_rawDescOnce sync.Once
-	file_gosdn_rbac_user_proto_rawDescData = file_gosdn_rbac_user_proto_rawDesc
+	file_gosdn_rbac_user_proto_rawDescData []byte
 )
 
 func file_gosdn_rbac_user_proto_rawDescGZIP() []byte {
 	file_gosdn_rbac_user_proto_rawDescOnce.Do(func() {
-		file_gosdn_rbac_user_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdn_rbac_user_proto_rawDescData)
+		file_gosdn_rbac_user_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gosdn_rbac_user_proto_rawDesc), len(file_gosdn_rbac_user_proto_rawDesc)))
 	})
 	return file_gosdn_rbac_user_proto_rawDescData
 }
@@ -909,7 +898,7 @@ func file_gosdn_rbac_user_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdn_rbac_user_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_gosdn_rbac_user_proto_rawDesc), len(file_gosdn_rbac_user_proto_rawDesc)),
 			NumEnums:      0,
 			NumMessages:   14,
 			NumExtensions: 0,
@@ -920,7 +909,6 @@ func file_gosdn_rbac_user_proto_init() {
 		MessageInfos:      file_gosdn_rbac_user_proto_msgTypes,
 	}.Build()
 	File_gosdn_rbac_user_proto = out.File
-	file_gosdn_rbac_user_proto_rawDesc = nil
 	file_gosdn_rbac_user_proto_goTypes = nil
 	file_gosdn_rbac_user_proto_depIdxs = nil
 }
diff --git a/api/go/gosdn/rbac/user.pb.gw.go b/api/go/gosdn/rbac/user.pb.gw.go
index 2103e85b5..ebe07c3c0 100755
--- a/api/go/gosdn/rbac/user.pb.gw.go
+++ b/api/go/gosdn/rbac/user.pb.gw.go
@@ -10,6 +10,7 @@ package rbac
 
 import (
 	"context"
+	"errors"
 	"io"
 	"net/http"
 
@@ -24,171 +25,158 @@ import (
 )
 
 // Suppress "imported and not used" errors
-var _ codes.Code
-var _ io.Reader
-var _ status.Status
-var _ = runtime.String
-var _ = utilities.NewDoubleArray
-var _ = metadata.Join
+var (
+	_ codes.Code
+	_ io.Reader
+	_ status.Status
+	_ = errors.New
+	_ = runtime.String
+	_ = utilities.NewDoubleArray
+	_ = metadata.Join
+)
 
 func request_UserService_CreateUsers_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq CreateUsersRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq CreateUsersRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.CreateUsers(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_UserService_CreateUsers_0(ctx context.Context, marshaler runtime.Marshaler, server UserServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq CreateUsersRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq CreateUsersRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.CreateUsers(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_UserService_GetUser_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
-)
+var filter_UserService_GetUser_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
 
 func request_UserService_GetUser_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetUserRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq GetUserRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_UserService_GetUser_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.GetUser(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_UserService_GetUser_0(ctx context.Context, marshaler runtime.Marshaler, server UserServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetUserRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq GetUserRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_UserService_GetUser_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.GetUser(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_UserService_GetUsers_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
-)
+var filter_UserService_GetUsers_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
 
 func request_UserService_GetUsers_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetUsersRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq GetUsersRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_UserService_GetUsers_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.GetUsers(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_UserService_GetUsers_0(ctx context.Context, marshaler runtime.Marshaler, server UserServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetUsersRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq GetUsersRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_UserService_GetUsers_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.GetUsers(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 func request_UserService_UpdateUsers_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq UpdateUsersRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq UpdateUsersRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.UpdateUsers(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_UserService_UpdateUsers_0(ctx context.Context, marshaler runtime.Marshaler, server UserServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq UpdateUsersRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq UpdateUsersRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.UpdateUsers(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_UserService_DeleteUsers_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
-)
+var filter_UserService_DeleteUsers_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
 
 func request_UserService_DeleteUsers_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeleteUsersRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq DeleteUsersRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_UserService_DeleteUsers_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.DeleteUsers(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_UserService_DeleteUsers_0(ctx context.Context, marshaler runtime.Marshaler, server UserServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeleteUsersRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq DeleteUsersRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_UserService_DeleteUsers_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.DeleteUsers(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 // RegisterUserServiceHandlerServer registers the http handlers for service UserService to "mux".
@@ -197,16 +185,13 @@ func local_request_UserService_DeleteUsers_0(ctx context.Context, marshaler runt
 // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterUserServiceHandlerFromEndpoint instead.
 // GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
 func RegisterUserServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server UserServiceServer) error {
-
-	mux.Handle("POST", pattern_UserService_CreateUsers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_UserService_CreateUsers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.UserService/CreateUsers", runtime.WithHTTPPathPattern("/users/create"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.UserService/CreateUsers", runtime.WithHTTPPathPattern("/users/create"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -218,20 +203,15 @@ func RegisterUserServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_UserService_CreateUsers_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_UserService_GetUser_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_UserService_GetUser_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.UserService/GetUser", runtime.WithHTTPPathPattern("/users/get"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.UserService/GetUser", runtime.WithHTTPPathPattern("/users/get"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -243,20 +223,15 @@ func RegisterUserServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_UserService_GetUser_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_UserService_GetUsers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_UserService_GetUsers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.UserService/GetUsers", runtime.WithHTTPPathPattern("/users"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.UserService/GetUsers", runtime.WithHTTPPathPattern("/users"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -268,20 +243,15 @@ func RegisterUserServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_UserService_GetUsers_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_UserService_UpdateUsers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_UserService_UpdateUsers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.UserService/UpdateUsers", runtime.WithHTTPPathPattern("/users/update"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.UserService/UpdateUsers", runtime.WithHTTPPathPattern("/users/update"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -293,20 +263,15 @@ func RegisterUserServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_UserService_UpdateUsers_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_UserService_DeleteUsers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_UserService_DeleteUsers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.UserService/DeleteUsers", runtime.WithHTTPPathPattern("/users/delete"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.rbac.UserService/DeleteUsers", runtime.WithHTTPPathPattern("/users/delete"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -318,9 +283,7 @@ func RegisterUserServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_UserService_DeleteUsers_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
 
 	return nil
@@ -347,7 +310,6 @@ func RegisterUserServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.Se
 			}
 		}()
 	}()
-
 	return RegisterUserServiceHandler(ctx, mux, conn)
 }
 
@@ -363,14 +325,11 @@ func RegisterUserServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn
 // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
 // "UserServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares.
 func RegisterUserServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client UserServiceClient) error {
-
-	mux.Handle("POST", pattern_UserService_CreateUsers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_UserService_CreateUsers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.UserService/CreateUsers", runtime.WithHTTPPathPattern("/users/create"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.UserService/CreateUsers", runtime.WithHTTPPathPattern("/users/create"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -381,18 +340,13 @@ func RegisterUserServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_UserService_CreateUsers_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_UserService_GetUser_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_UserService_GetUser_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.UserService/GetUser", runtime.WithHTTPPathPattern("/users/get"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.UserService/GetUser", runtime.WithHTTPPathPattern("/users/get"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -403,18 +357,13 @@ func RegisterUserServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_UserService_GetUser_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_UserService_GetUsers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_UserService_GetUsers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.UserService/GetUsers", runtime.WithHTTPPathPattern("/users"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.UserService/GetUsers", runtime.WithHTTPPathPattern("/users"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -425,18 +374,13 @@ func RegisterUserServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_UserService_GetUsers_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_UserService_UpdateUsers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_UserService_UpdateUsers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.UserService/UpdateUsers", runtime.WithHTTPPathPattern("/users/update"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.UserService/UpdateUsers", runtime.WithHTTPPathPattern("/users/update"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -447,18 +391,13 @@ func RegisterUserServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_UserService_UpdateUsers_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_UserService_DeleteUsers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_UserService_DeleteUsers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.UserService/DeleteUsers", runtime.WithHTTPPathPattern("/users/delete"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.rbac.UserService/DeleteUsers", runtime.WithHTTPPathPattern("/users/delete"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -469,34 +408,23 @@ func RegisterUserServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_UserService_DeleteUsers_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
 	return nil
 }
 
 var (
 	pattern_UserService_CreateUsers_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"users", "create"}, ""))
-
-	pattern_UserService_GetUser_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"users", "get"}, ""))
-
-	pattern_UserService_GetUsers_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"users"}, ""))
-
+	pattern_UserService_GetUser_0     = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"users", "get"}, ""))
+	pattern_UserService_GetUsers_0    = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"users"}, ""))
 	pattern_UserService_UpdateUsers_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"users", "update"}, ""))
-
 	pattern_UserService_DeleteUsers_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"users", "delete"}, ""))
 )
 
 var (
 	forward_UserService_CreateUsers_0 = runtime.ForwardResponseMessage
-
-	forward_UserService_GetUser_0 = runtime.ForwardResponseMessage
-
-	forward_UserService_GetUsers_0 = runtime.ForwardResponseMessage
-
+	forward_UserService_GetUser_0     = runtime.ForwardResponseMessage
+	forward_UserService_GetUsers_0    = runtime.ForwardResponseMessage
 	forward_UserService_UpdateUsers_0 = runtime.ForwardResponseMessage
-
 	forward_UserService_DeleteUsers_0 = runtime.ForwardResponseMessage
 )
diff --git a/api/go/gosdn/southbound/southbound.pb.go b/api/go/gosdn/southbound/southbound.pb.go
index bf475590f..ea26197dc 100755
--- a/api/go/gosdn/southbound/southbound.pb.go
+++ b/api/go/gosdn/southbound/southbound.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: gosdn/southbound/southbound.proto
 
@@ -12,6 +12,7 @@ import (
 	_ "google.golang.org/protobuf/types/descriptorpb"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -76,13 +77,12 @@ func (Type) EnumDescriptor() ([]byte, []int) {
 }
 
 type GetSchemaRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Pid           string                 `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
+	Sid           string                 `protobuf:"bytes,3,opt,name=sid,proto3" json:"sid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Pid       string `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
-	Sid       string `protobuf:"bytes,3,opt,name=sid,proto3" json:"sid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetSchemaRequest) Reset() {
@@ -137,11 +137,10 @@ func (x *GetSchemaRequest) GetSid() string {
 }
 
 type Payload struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Chunk         []byte                 `protobuf:"bytes,1,opt,name=chunk,proto3" json:"chunk,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Chunk []byte `protobuf:"bytes,1,opt,name=chunk,proto3" json:"chunk,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Payload) Reset() {
@@ -182,12 +181,11 @@ func (x *Payload) GetChunk() []byte {
 }
 
 type SouthboundInterface struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Id            string                 `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	Type          Type                   `protobuf:"varint,2,opt,name=type,proto3,enum=gosdn.southbound.Type" json:"type,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Id   string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	Type Type   `protobuf:"varint,2,opt,name=type,proto3,enum=gosdn.southbound.Type" json:"type,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *SouthboundInterface) Reset() {
@@ -236,7 +234,7 @@ func (x *SouthboundInterface) GetType() Type {
 
 var File_gosdn_southbound_southbound_proto protoreflect.FileDescriptor
 
-var file_gosdn_southbound_southbound_proto_rawDesc = []byte{
+var file_gosdn_southbound_southbound_proto_rawDesc = string([]byte{
 	0x0a, 0x21, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x73, 0x6f, 0x75, 0x74, 0x68, 0x62, 0x6f, 0x75,
 	0x6e, 0x64, 0x2f, 0x73, 0x6f, 0x75, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x70, 0x72,
 	0x6f, 0x74, 0x6f, 0x12, 0x10, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x73, 0x6f, 0x75, 0x74, 0x68,
@@ -271,16 +269,16 @@ var file_gosdn_southbound_southbound_proto_rawDesc = []byte{
 	0x6e, 0x65, 0x74, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f,
 	0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x73, 0x6f, 0x75, 0x74, 0x68, 0x62, 0x6f, 0x75, 0x6e,
 	0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_gosdn_southbound_southbound_proto_rawDescOnce sync.Once
-	file_gosdn_southbound_southbound_proto_rawDescData = file_gosdn_southbound_southbound_proto_rawDesc
+	file_gosdn_southbound_southbound_proto_rawDescData []byte
 )
 
 func file_gosdn_southbound_southbound_proto_rawDescGZIP() []byte {
 	file_gosdn_southbound_southbound_proto_rawDescOnce.Do(func() {
-		file_gosdn_southbound_southbound_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdn_southbound_southbound_proto_rawDescData)
+		file_gosdn_southbound_southbound_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gosdn_southbound_southbound_proto_rawDesc), len(file_gosdn_southbound_southbound_proto_rawDesc)))
 	})
 	return file_gosdn_southbound_southbound_proto_rawDescData
 }
@@ -313,7 +311,7 @@ func file_gosdn_southbound_southbound_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdn_southbound_southbound_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_gosdn_southbound_southbound_proto_rawDesc), len(file_gosdn_southbound_southbound_proto_rawDesc)),
 			NumEnums:      1,
 			NumMessages:   3,
 			NumExtensions: 0,
@@ -325,7 +323,6 @@ func file_gosdn_southbound_southbound_proto_init() {
 		MessageInfos:      file_gosdn_southbound_southbound_proto_msgTypes,
 	}.Build()
 	File_gosdn_southbound_southbound_proto = out.File
-	file_gosdn_southbound_southbound_proto_rawDesc = nil
 	file_gosdn_southbound_southbound_proto_goTypes = nil
 	file_gosdn_southbound_southbound_proto_depIdxs = nil
 }
diff --git a/api/go/gosdn/subscriptionmanagement/subscriptionmanagement.pb.go b/api/go/gosdn/subscriptionmanagement/subscriptionmanagement.pb.go
index 1691a7cf1..6bfb0e28a 100755
--- a/api/go/gosdn/subscriptionmanagement/subscriptionmanagement.pb.go
+++ b/api/go/gosdn/subscriptionmanagement/subscriptionmanagement.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: gosdn/subscriptionmanagement/subscriptionmanagement.proto
 
@@ -14,6 +14,7 @@ import (
 	_ "google.golang.org/protobuf/types/descriptorpb"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -24,16 +25,15 @@ const (
 )
 
 type Subscription struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Subid            string            `protobuf:"bytes,1,opt,name=subid,proto3" json:"subid,omitempty"`
-	Pid              string            `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
-	Mneid            string            `protobuf:"bytes,3,opt,name=mneid,proto3" json:"mneid,omitempty"`
-	MneName          string            `protobuf:"bytes,4,opt,name=mne_name,json=mneName,proto3" json:"mne_name,omitempty"`
-	Paths            []*Path           `protobuf:"bytes,5,rep,name=paths,proto3" json:"paths,omitempty"`
-	SubscribeOptions *SubscribeOptions `protobuf:"bytes,6,opt,name=subscribe_options,json=subscribeOptions,proto3" json:"subscribe_options,omitempty"`
+	state            protoimpl.MessageState `protogen:"open.v1"`
+	Subid            string                 `protobuf:"bytes,1,opt,name=subid,proto3" json:"subid,omitempty"`
+	Pid              string                 `protobuf:"bytes,2,opt,name=pid,proto3" json:"pid,omitempty"`
+	Mneid            string                 `protobuf:"bytes,3,opt,name=mneid,proto3" json:"mneid,omitempty"`
+	MneName          string                 `protobuf:"bytes,4,opt,name=mne_name,json=mneName,proto3" json:"mne_name,omitempty"`
+	Paths            []*Path                `protobuf:"bytes,5,rep,name=paths,proto3" json:"paths,omitempty"`
+	SubscribeOptions *SubscribeOptions      `protobuf:"bytes,6,opt,name=subscribe_options,json=subscribeOptions,proto3" json:"subscribe_options,omitempty"`
+	unknownFields    protoimpl.UnknownFields
+	sizeCache        protoimpl.SizeCache
 }
 
 func (x *Subscription) Reset() {
@@ -109,11 +109,10 @@ func (x *Subscription) GetSubscribeOptions() *SubscribeOptions {
 }
 
 type Path struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Elem          []string               `protobuf:"bytes,1,rep,name=elem,proto3" json:"elem,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Elem []string `protobuf:"bytes,1,rep,name=elem,proto3" json:"elem,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Path) Reset() {
@@ -154,13 +153,12 @@ func (x *Path) GetElem() []string {
 }
 
 type SubscribeOptions struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	GnmiMode       string `protobuf:"bytes,1,opt,name=gnmi_mode,json=gnmiMode,proto3" json:"gnmi_mode,omitempty"`
-	GnmiStreamMode string `protobuf:"bytes,2,opt,name=gnmi_stream_mode,json=gnmiStreamMode,proto3" json:"gnmi_stream_mode,omitempty"`
-	SampleInterval uint64 `protobuf:"varint,3,opt,name=sample_interval,json=sampleInterval,proto3" json:"sample_interval,omitempty"`
+	state          protoimpl.MessageState `protogen:"open.v1"`
+	GnmiMode       string                 `protobuf:"bytes,1,opt,name=gnmi_mode,json=gnmiMode,proto3" json:"gnmi_mode,omitempty"`
+	GnmiStreamMode string                 `protobuf:"bytes,2,opt,name=gnmi_stream_mode,json=gnmiStreamMode,proto3" json:"gnmi_stream_mode,omitempty"`
+	SampleInterval uint64                 `protobuf:"varint,3,opt,name=sample_interval,json=sampleInterval,proto3" json:"sample_interval,omitempty"`
+	unknownFields  protoimpl.UnknownFields
+	sizeCache      protoimpl.SizeCache
 }
 
 func (x *SubscribeOptions) Reset() {
@@ -215,11 +213,10 @@ func (x *SubscribeOptions) GetSampleInterval() uint64 {
 }
 
 type GetAllRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetAllRequest) Reset() {
@@ -260,12 +257,11 @@ func (x *GetAllRequest) GetTimestamp() int64 {
 }
 
 type GetAllResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Subscriptions []*Subscription        `protobuf:"bytes,2,rep,name=subscriptions,proto3" json:"subscriptions,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp     int64           `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Subscriptions []*Subscription `protobuf:"bytes,2,rep,name=subscriptions,proto3" json:"subscriptions,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetAllResponse) Reset() {
@@ -313,12 +309,11 @@ func (x *GetAllResponse) GetSubscriptions() []*Subscription {
 }
 
 type GetRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Subid         string                 `protobuf:"bytes,2,opt,name=subid,proto3" json:"subid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Subid     string `protobuf:"bytes,2,opt,name=subid,proto3" json:"subid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetRequest) Reset() {
@@ -366,12 +361,11 @@ func (x *GetRequest) GetSubid() string {
 }
 
 type GetResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Subscriptions *Subscription          `protobuf:"bytes,2,opt,name=subscriptions,proto3" json:"subscriptions,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp     int64         `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Subscriptions *Subscription `protobuf:"bytes,2,opt,name=subscriptions,proto3" json:"subscriptions,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetResponse) Reset() {
@@ -419,12 +413,11 @@ func (x *GetResponse) GetSubscriptions() *Subscription {
 }
 
 type DeleteRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Subid         string                 `protobuf:"bytes,2,opt,name=subid,proto3" json:"subid,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Subid     string `protobuf:"bytes,2,opt,name=subid,proto3" json:"subid,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeleteRequest) Reset() {
@@ -472,11 +465,10 @@ func (x *DeleteRequest) GetSubid() string {
 }
 
 type DeleteResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeleteResponse) Reset() {
@@ -517,13 +509,12 @@ func (x *DeleteResponse) GetTimestamp() int64 {
 }
 
 type AddRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Mneid         string                 `protobuf:"bytes,2,opt,name=mneid,proto3" json:"mneid,omitempty"`
+	Subscription  *Subscription          `protobuf:"bytes,3,opt,name=subscription,proto3" json:"subscription,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp    int64         `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Mneid        string        `protobuf:"bytes,2,opt,name=mneid,proto3" json:"mneid,omitempty"`
-	Subscription *Subscription `protobuf:"bytes,3,opt,name=subscription,proto3" json:"subscription,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *AddRequest) Reset() {
@@ -578,11 +569,10 @@ func (x *AddRequest) GetSubscription() *Subscription {
 }
 
 type AddResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *AddResponse) Reset() {
@@ -623,11 +613,10 @@ func (x *AddResponse) GetTimestamp() int64 {
 }
 
 type ResetAllSubscriptionsRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *ResetAllSubscriptionsRequest) Reset() {
@@ -668,11 +657,10 @@ func (x *ResetAllSubscriptionsRequest) GetTimestamp() int64 {
 }
 
 type ResetAllSubscriptionsResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *ResetAllSubscriptionsResponse) Reset() {
@@ -714,7 +702,7 @@ func (x *ResetAllSubscriptionsResponse) GetTimestamp() int64 {
 
 var File_gosdn_subscriptionmanagement_subscriptionmanagement_proto protoreflect.FileDescriptor
 
-var file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_rawDesc = []byte{
+var file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_rawDesc = string([]byte{
 	0x0a, 0x39, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70,
 	0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2f, 0x73,
 	0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x61, 0x6e, 0x61, 0x67,
@@ -855,16 +843,16 @@ var file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_rawDesc = []b
 	0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70,
 	0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x61,
 	0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_rawDescOnce sync.Once
-	file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_rawDescData = file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_rawDesc
+	file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_rawDescData []byte
 )
 
 func file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_rawDescGZIP() []byte {
 	file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_rawDescOnce.Do(func() {
-		file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_rawDescData)
+		file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_rawDesc), len(file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_rawDesc)))
 	})
 	return file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_rawDescData
 }
@@ -917,7 +905,7 @@ func file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_rawDesc), len(file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_rawDesc)),
 			NumEnums:      0,
 			NumMessages:   13,
 			NumExtensions: 0,
@@ -928,7 +916,6 @@ func file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_init() {
 		MessageInfos:      file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_msgTypes,
 	}.Build()
 	File_gosdn_subscriptionmanagement_subscriptionmanagement_proto = out.File
-	file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_rawDesc = nil
 	file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_goTypes = nil
 	file_gosdn_subscriptionmanagement_subscriptionmanagement_proto_depIdxs = nil
 }
diff --git a/api/go/gosdn/subscriptionmanagement/subscriptionmanagement.pb.gw.go b/api/go/gosdn/subscriptionmanagement/subscriptionmanagement.pb.gw.go
index b7efc5dc0..40aebfa6e 100755
--- a/api/go/gosdn/subscriptionmanagement/subscriptionmanagement.pb.gw.go
+++ b/api/go/gosdn/subscriptionmanagement/subscriptionmanagement.pb.gw.go
@@ -10,6 +10,7 @@ package submanagement
 
 import (
 	"context"
+	"errors"
 	"io"
 	"net/http"
 
@@ -24,283 +25,220 @@ import (
 )
 
 // Suppress "imported and not used" errors
-var _ codes.Code
-var _ io.Reader
-var _ status.Status
-var _ = runtime.String
-var _ = utilities.NewDoubleArray
-var _ = metadata.Join
-
 var (
-	filter_SubscriptionManagementService_GetAll_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
+	_ codes.Code
+	_ io.Reader
+	_ status.Status
+	_ = errors.New
+	_ = runtime.String
+	_ = utilities.NewDoubleArray
+	_ = metadata.Join
 )
 
-func request_SubscriptionManagementService_GetAll_0(ctx context.Context, marshaler runtime.Marshaler, client SubscriptionManagementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetAllRequest
-	var metadata runtime.ServerMetadata
+var filter_SubscriptionManagementService_GetAll_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
 
+func request_SubscriptionManagementService_GetAll_0(ctx context.Context, marshaler runtime.Marshaler, client SubscriptionManagementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+	var (
+		protoReq GetAllRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_SubscriptionManagementService_GetAll_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.GetAll(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_SubscriptionManagementService_GetAll_0(ctx context.Context, marshaler runtime.Marshaler, server SubscriptionManagementServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetAllRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq GetAllRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_SubscriptionManagementService_GetAll_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.GetAll(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_SubscriptionManagementService_Get_0 = &utilities.DoubleArray{Encoding: map[string]int{"subid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
-)
+var filter_SubscriptionManagementService_Get_0 = &utilities.DoubleArray{Encoding: map[string]int{"subid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
 
 func request_SubscriptionManagementService_Get_0(ctx context.Context, marshaler runtime.Marshaler, client SubscriptionManagementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq GetRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["subid"]
+	val, ok := pathParams["subid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "subid")
 	}
-
 	protoReq.Subid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "subid", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_SubscriptionManagementService_Get_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.Get(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_SubscriptionManagementService_Get_0(ctx context.Context, marshaler runtime.Marshaler, server SubscriptionManagementServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq GetRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["subid"]
+	val, ok := pathParams["subid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "subid")
 	}
-
 	protoReq.Subid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "subid", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_SubscriptionManagementService_Get_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.Get(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_SubscriptionManagementService_Delete_0 = &utilities.DoubleArray{Encoding: map[string]int{"subid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
-)
+var filter_SubscriptionManagementService_Delete_0 = &utilities.DoubleArray{Encoding: map[string]int{"subid": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
 
 func request_SubscriptionManagementService_Delete_0(ctx context.Context, marshaler runtime.Marshaler, client SubscriptionManagementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeleteRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq DeleteRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["subid"]
+	val, ok := pathParams["subid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "subid")
 	}
-
 	protoReq.Subid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "subid", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_SubscriptionManagementService_Delete_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.Delete(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_SubscriptionManagementService_Delete_0(ctx context.Context, marshaler runtime.Marshaler, server SubscriptionManagementServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeleteRequest
-	var metadata runtime.ServerMetadata
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq DeleteRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["subid"]
+	val, ok := pathParams["subid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "subid")
 	}
-
 	protoReq.Subid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "subid", err)
 	}
-
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_SubscriptionManagementService_Delete_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.Delete(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 func request_SubscriptionManagementService_Add_0(ctx context.Context, marshaler runtime.Marshaler, client SubscriptionManagementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq AddRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
-	}
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq AddRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["mneid"]
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	val, ok := pathParams["mneid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "mneid")
 	}
-
 	protoReq.Mneid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "mneid", err)
 	}
-
 	msg, err := client.Add(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_SubscriptionManagementService_Add_0(ctx context.Context, marshaler runtime.Marshaler, server SubscriptionManagementServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq AddRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
-		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
-	}
-
 	var (
-		val string
-		ok  bool
-		err error
-		_   = err
+		protoReq AddRequest
+		metadata runtime.ServerMetadata
+		err      error
 	)
-
-	val, ok = pathParams["mneid"]
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
+		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+	}
+	val, ok := pathParams["mneid"]
 	if !ok {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "mneid")
 	}
-
 	protoReq.Mneid, err = runtime.String(val)
 	if err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "mneid", err)
 	}
-
 	msg, err := server.Add(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_SubscriptionManagementService_ResetAllSubscriptions_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
-)
+var filter_SubscriptionManagementService_ResetAllSubscriptions_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
 
 func request_SubscriptionManagementService_ResetAllSubscriptions_0(ctx context.Context, marshaler runtime.Marshaler, client SubscriptionManagementServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq ResetAllSubscriptionsRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq ResetAllSubscriptionsRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_SubscriptionManagementService_ResetAllSubscriptions_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.ResetAllSubscriptions(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_SubscriptionManagementService_ResetAllSubscriptions_0(ctx context.Context, marshaler runtime.Marshaler, server SubscriptionManagementServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq ResetAllSubscriptionsRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq ResetAllSubscriptionsRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_SubscriptionManagementService_ResetAllSubscriptions_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.ResetAllSubscriptions(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 // RegisterSubscriptionManagementServiceHandlerServer registers the http handlers for service SubscriptionManagementService to "mux".
@@ -309,16 +247,13 @@ func local_request_SubscriptionManagementService_ResetAllSubscriptions_0(ctx con
 // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterSubscriptionManagementServiceHandlerFromEndpoint instead.
 // GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
 func RegisterSubscriptionManagementServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server SubscriptionManagementServiceServer) error {
-
-	mux.Handle("GET", pattern_SubscriptionManagementService_GetAll_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_SubscriptionManagementService_GetAll_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.subscriptionmanagement.SubscriptionManagementService/GetAll", runtime.WithHTTPPathPattern("/submanagement/subscriptions"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.subscriptionmanagement.SubscriptionManagementService/GetAll", runtime.WithHTTPPathPattern("/submanagement/subscriptions"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -330,20 +265,15 @@ func RegisterSubscriptionManagementServiceHandlerServer(ctx context.Context, mux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_SubscriptionManagementService_GetAll_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_SubscriptionManagementService_Get_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_SubscriptionManagementService_Get_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.subscriptionmanagement.SubscriptionManagementService/Get", runtime.WithHTTPPathPattern("/submanagement/{subid}"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.subscriptionmanagement.SubscriptionManagementService/Get", runtime.WithHTTPPathPattern("/submanagement/{subid}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -355,20 +285,15 @@ func RegisterSubscriptionManagementServiceHandlerServer(ctx context.Context, mux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_SubscriptionManagementService_Get_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_SubscriptionManagementService_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_SubscriptionManagementService_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.subscriptionmanagement.SubscriptionManagementService/Delete", runtime.WithHTTPPathPattern("/submanagement/{subid}"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.subscriptionmanagement.SubscriptionManagementService/Delete", runtime.WithHTTPPathPattern("/submanagement/{subid}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -380,20 +305,15 @@ func RegisterSubscriptionManagementServiceHandlerServer(ctx context.Context, mux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_SubscriptionManagementService_Delete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_SubscriptionManagementService_Add_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_SubscriptionManagementService_Add_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.subscriptionmanagement.SubscriptionManagementService/Add", runtime.WithHTTPPathPattern("/submanagement/{mneid}"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.subscriptionmanagement.SubscriptionManagementService/Add", runtime.WithHTTPPathPattern("/submanagement/{mneid}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -405,20 +325,15 @@ func RegisterSubscriptionManagementServiceHandlerServer(ctx context.Context, mux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_SubscriptionManagementService_Add_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_SubscriptionManagementService_ResetAllSubscriptions_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_SubscriptionManagementService_ResetAllSubscriptions_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.subscriptionmanagement.SubscriptionManagementService/ResetAllSubscriptions", runtime.WithHTTPPathPattern("/submanagement/reset"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.subscriptionmanagement.SubscriptionManagementService/ResetAllSubscriptions", runtime.WithHTTPPathPattern("/submanagement/reset"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -430,9 +345,7 @@ func RegisterSubscriptionManagementServiceHandlerServer(ctx context.Context, mux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_SubscriptionManagementService_ResetAllSubscriptions_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
 
 	return nil
@@ -459,7 +372,6 @@ func RegisterSubscriptionManagementServiceHandlerFromEndpoint(ctx context.Contex
 			}
 		}()
 	}()
-
 	return RegisterSubscriptionManagementServiceHandler(ctx, mux, conn)
 }
 
@@ -475,14 +387,11 @@ func RegisterSubscriptionManagementServiceHandler(ctx context.Context, mux *runt
 // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
 // "SubscriptionManagementServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares.
 func RegisterSubscriptionManagementServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client SubscriptionManagementServiceClient) error {
-
-	mux.Handle("GET", pattern_SubscriptionManagementService_GetAll_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_SubscriptionManagementService_GetAll_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.subscriptionmanagement.SubscriptionManagementService/GetAll", runtime.WithHTTPPathPattern("/submanagement/subscriptions"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.subscriptionmanagement.SubscriptionManagementService/GetAll", runtime.WithHTTPPathPattern("/submanagement/subscriptions"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -493,18 +402,13 @@ func RegisterSubscriptionManagementServiceHandlerClient(ctx context.Context, mux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_SubscriptionManagementService_GetAll_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_SubscriptionManagementService_Get_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_SubscriptionManagementService_Get_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.subscriptionmanagement.SubscriptionManagementService/Get", runtime.WithHTTPPathPattern("/submanagement/{subid}"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.subscriptionmanagement.SubscriptionManagementService/Get", runtime.WithHTTPPathPattern("/submanagement/{subid}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -515,18 +419,13 @@ func RegisterSubscriptionManagementServiceHandlerClient(ctx context.Context, mux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_SubscriptionManagementService_Get_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_SubscriptionManagementService_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_SubscriptionManagementService_Delete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.subscriptionmanagement.SubscriptionManagementService/Delete", runtime.WithHTTPPathPattern("/submanagement/{subid}"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.subscriptionmanagement.SubscriptionManagementService/Delete", runtime.WithHTTPPathPattern("/submanagement/{subid}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -537,18 +436,13 @@ func RegisterSubscriptionManagementServiceHandlerClient(ctx context.Context, mux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_SubscriptionManagementService_Delete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_SubscriptionManagementService_Add_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_SubscriptionManagementService_Add_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.subscriptionmanagement.SubscriptionManagementService/Add", runtime.WithHTTPPathPattern("/submanagement/{mneid}"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.subscriptionmanagement.SubscriptionManagementService/Add", runtime.WithHTTPPathPattern("/submanagement/{mneid}"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -559,18 +453,13 @@ func RegisterSubscriptionManagementServiceHandlerClient(ctx context.Context, mux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_SubscriptionManagementService_Add_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_SubscriptionManagementService_ResetAllSubscriptions_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_SubscriptionManagementService_ResetAllSubscriptions_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.subscriptionmanagement.SubscriptionManagementService/ResetAllSubscriptions", runtime.WithHTTPPathPattern("/submanagement/reset"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.subscriptionmanagement.SubscriptionManagementService/ResetAllSubscriptions", runtime.WithHTTPPathPattern("/submanagement/reset"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -581,34 +470,23 @@ func RegisterSubscriptionManagementServiceHandlerClient(ctx context.Context, mux
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_SubscriptionManagementService_ResetAllSubscriptions_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
 	return nil
 }
 
 var (
-	pattern_SubscriptionManagementService_GetAll_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"submanagement", "subscriptions"}, ""))
-
-	pattern_SubscriptionManagementService_Get_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"submanagement", "subid"}, ""))
-
-	pattern_SubscriptionManagementService_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"submanagement", "subid"}, ""))
-
-	pattern_SubscriptionManagementService_Add_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"submanagement", "mneid"}, ""))
-
+	pattern_SubscriptionManagementService_GetAll_0                = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"submanagement", "subscriptions"}, ""))
+	pattern_SubscriptionManagementService_Get_0                   = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"submanagement", "subid"}, ""))
+	pattern_SubscriptionManagementService_Delete_0                = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"submanagement", "subid"}, ""))
+	pattern_SubscriptionManagementService_Add_0                   = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"submanagement", "mneid"}, ""))
 	pattern_SubscriptionManagementService_ResetAllSubscriptions_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"submanagement", "reset"}, ""))
 )
 
 var (
-	forward_SubscriptionManagementService_GetAll_0 = runtime.ForwardResponseMessage
-
-	forward_SubscriptionManagementService_Get_0 = runtime.ForwardResponseMessage
-
-	forward_SubscriptionManagementService_Delete_0 = runtime.ForwardResponseMessage
-
-	forward_SubscriptionManagementService_Add_0 = runtime.ForwardResponseMessage
-
+	forward_SubscriptionManagementService_GetAll_0                = runtime.ForwardResponseMessage
+	forward_SubscriptionManagementService_Get_0                   = runtime.ForwardResponseMessage
+	forward_SubscriptionManagementService_Delete_0                = runtime.ForwardResponseMessage
+	forward_SubscriptionManagementService_Add_0                   = runtime.ForwardResponseMessage
 	forward_SubscriptionManagementService_ResetAllSubscriptions_0 = runtime.ForwardResponseMessage
 )
diff --git a/api/go/gosdn/topology/link.pb.go b/api/go/gosdn/topology/link.pb.go
index 398feb9d9..d18acbd1b 100755
--- a/api/go/gosdn/topology/link.pb.go
+++ b/api/go/gosdn/topology/link.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: gosdn/topology/link.proto
 
@@ -16,6 +16,7 @@ import (
 	_ "google.golang.org/protobuf/types/descriptorpb"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -26,17 +27,16 @@ const (
 )
 
 type Link struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Id            string                 `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	Name          string                 `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+	SourceNode    *Node                  `protobuf:"bytes,3,opt,name=sourceNode,proto3" json:"sourceNode,omitempty"`
+	TargetNode    *Node                  `protobuf:"bytes,4,opt,name=targetNode,proto3" json:"targetNode,omitempty"`
+	SourcePort    *Port                  `protobuf:"bytes,5,opt,name=sourcePort,proto3" json:"sourcePort,omitempty"`
+	TargetPort    *Port                  `protobuf:"bytes,6,opt,name=targetPort,proto3" json:"targetPort,omitempty"`
+	Metadata      *conflict.Metadata     `protobuf:"bytes,7,opt,name=metadata,proto3" json:"metadata,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Id         string             `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	Name       string             `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
-	SourceNode *Node              `protobuf:"bytes,3,opt,name=sourceNode,proto3" json:"sourceNode,omitempty"`
-	TargetNode *Node              `protobuf:"bytes,4,opt,name=targetNode,proto3" json:"targetNode,omitempty"`
-	SourcePort *Port              `protobuf:"bytes,5,opt,name=sourcePort,proto3" json:"sourcePort,omitempty"`
-	TargetPort *Port              `protobuf:"bytes,6,opt,name=targetPort,proto3" json:"targetPort,omitempty"`
-	Metadata   *conflict.Metadata `protobuf:"bytes,7,opt,name=metadata,proto3" json:"metadata,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Link) Reset() {
@@ -120,7 +120,7 @@ func (x *Link) GetMetadata() *conflict.Metadata {
 
 var File_gosdn_topology_link_proto protoreflect.FileDescriptor
 
-var file_gosdn_topology_link_proto_rawDesc = []byte{
+var file_gosdn_topology_link_proto_rawDesc = string([]byte{
 	0x0a, 0x19, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79,
 	0x2f, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x67, 0x6f, 0x73,
 	0x64, 0x6e, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x1a, 0x1c, 0x67, 0x6f, 0x6f,
@@ -164,16 +164,16 @@ var file_gosdn_topology_link_proto_rawDesc = []byte{
 	0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67, 0x6f, 0x73, 0x64,
 	0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x74,
 	0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_gosdn_topology_link_proto_rawDescOnce sync.Once
-	file_gosdn_topology_link_proto_rawDescData = file_gosdn_topology_link_proto_rawDesc
+	file_gosdn_topology_link_proto_rawDescData []byte
 )
 
 func file_gosdn_topology_link_proto_rawDescGZIP() []byte {
 	file_gosdn_topology_link_proto_rawDescOnce.Do(func() {
-		file_gosdn_topology_link_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdn_topology_link_proto_rawDescData)
+		file_gosdn_topology_link_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gosdn_topology_link_proto_rawDesc), len(file_gosdn_topology_link_proto_rawDesc)))
 	})
 	return file_gosdn_topology_link_proto_rawDescData
 }
@@ -209,7 +209,7 @@ func file_gosdn_topology_link_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdn_topology_link_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_gosdn_topology_link_proto_rawDesc), len(file_gosdn_topology_link_proto_rawDesc)),
 			NumEnums:      0,
 			NumMessages:   1,
 			NumExtensions: 0,
@@ -220,7 +220,6 @@ func file_gosdn_topology_link_proto_init() {
 		MessageInfos:      file_gosdn_topology_link_proto_msgTypes,
 	}.Build()
 	File_gosdn_topology_link_proto = out.File
-	file_gosdn_topology_link_proto_rawDesc = nil
 	file_gosdn_topology_link_proto_goTypes = nil
 	file_gosdn_topology_link_proto_depIdxs = nil
 }
diff --git a/api/go/gosdn/topology/node.pb.go b/api/go/gosdn/topology/node.pb.go
index b65392c17..d9c0e5af1 100755
--- a/api/go/gosdn/topology/node.pb.go
+++ b/api/go/gosdn/topology/node.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: gosdn/topology/node.proto
 
@@ -16,6 +16,7 @@ import (
 	_ "google.golang.org/protobuf/types/descriptorpb"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -26,13 +27,12 @@ const (
 )
 
 type Node struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Id            string                 `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	Name          string                 `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+	Metadata      *conflict.Metadata     `protobuf:"bytes,3,opt,name=metadata,proto3" json:"metadata,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Id       string             `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	Name     string             `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
-	Metadata *conflict.Metadata `protobuf:"bytes,3,opt,name=metadata,proto3" json:"metadata,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Node) Reset() {
@@ -88,7 +88,7 @@ func (x *Node) GetMetadata() *conflict.Metadata {
 
 var File_gosdn_topology_node_proto protoreflect.FileDescriptor
 
-var file_gosdn_topology_node_proto_rawDesc = []byte{
+var file_gosdn_topology_node_proto_rawDesc = string([]byte{
 	0x0a, 0x19, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79,
 	0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x67, 0x6f, 0x73,
 	0x64, 0x6e, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x1a, 0x1c, 0x67, 0x6f, 0x6f,
@@ -113,16 +113,16 @@ var file_gosdn_topology_node_proto_rawDesc = []byte{
 	0x2d, 0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67, 0x6f, 0x73,
 	0x64, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f,
 	0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_gosdn_topology_node_proto_rawDescOnce sync.Once
-	file_gosdn_topology_node_proto_rawDescData = file_gosdn_topology_node_proto_rawDesc
+	file_gosdn_topology_node_proto_rawDescData []byte
 )
 
 func file_gosdn_topology_node_proto_rawDescGZIP() []byte {
 	file_gosdn_topology_node_proto_rawDescOnce.Do(func() {
-		file_gosdn_topology_node_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdn_topology_node_proto_rawDescData)
+		file_gosdn_topology_node_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gosdn_topology_node_proto_rawDesc), len(file_gosdn_topology_node_proto_rawDesc)))
 	})
 	return file_gosdn_topology_node_proto_rawDescData
 }
@@ -150,7 +150,7 @@ func file_gosdn_topology_node_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdn_topology_node_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_gosdn_topology_node_proto_rawDesc), len(file_gosdn_topology_node_proto_rawDesc)),
 			NumEnums:      0,
 			NumMessages:   1,
 			NumExtensions: 0,
@@ -161,7 +161,6 @@ func file_gosdn_topology_node_proto_init() {
 		MessageInfos:      file_gosdn_topology_node_proto_msgTypes,
 	}.Build()
 	File_gosdn_topology_node_proto = out.File
-	file_gosdn_topology_node_proto_rawDesc = nil
 	file_gosdn_topology_node_proto_goTypes = nil
 	file_gosdn_topology_node_proto_depIdxs = nil
 }
diff --git a/api/go/gosdn/topology/port.pb.go b/api/go/gosdn/topology/port.pb.go
index de83b8af4..383452572 100755
--- a/api/go/gosdn/topology/port.pb.go
+++ b/api/go/gosdn/topology/port.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: gosdn/topology/port.proto
 
@@ -16,6 +16,7 @@ import (
 	_ "google.golang.org/protobuf/types/descriptorpb"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -26,12 +27,11 @@ const (
 )
 
 type Configuration struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Ip            string                 `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"`
+	PrefixLength  int64                  `protobuf:"varint,2,opt,name=prefixLength,proto3" json:"prefixLength,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Ip           string `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"`
-	PrefixLength int64  `protobuf:"varint,2,opt,name=prefixLength,proto3" json:"prefixLength,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Configuration) Reset() {
@@ -79,14 +79,13 @@ func (x *Configuration) GetPrefixLength() int64 {
 }
 
 type Port struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Id            string                 `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	Name          string                 `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+	Configuration *Configuration         `protobuf:"bytes,3,opt,name=configuration,proto3" json:"configuration,omitempty"`
+	Metadata      *conflict.Metadata     `protobuf:"bytes,4,opt,name=metadata,proto3" json:"metadata,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Id            string             `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	Name          string             `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
-	Configuration *Configuration     `protobuf:"bytes,3,opt,name=configuration,proto3" json:"configuration,omitempty"`
-	Metadata      *conflict.Metadata `protobuf:"bytes,4,opt,name=metadata,proto3" json:"metadata,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Port) Reset() {
@@ -149,7 +148,7 @@ func (x *Port) GetMetadata() *conflict.Metadata {
 
 var File_gosdn_topology_port_proto protoreflect.FileDescriptor
 
-var file_gosdn_topology_port_proto_rawDesc = []byte{
+var file_gosdn_topology_port_proto_rawDesc = string([]byte{
 	0x0a, 0x19, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79,
 	0x2f, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x67, 0x6f, 0x73,
 	0x64, 0x6e, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x1a, 0x1c, 0x67, 0x6f, 0x6f,
@@ -185,16 +184,16 @@ var file_gosdn_topology_port_proto_rawDesc = []byte{
 	0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f,
 	0x73, 0x64, 0x6e, 0x2f, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x62, 0x06, 0x70, 0x72,
 	0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_gosdn_topology_port_proto_rawDescOnce sync.Once
-	file_gosdn_topology_port_proto_rawDescData = file_gosdn_topology_port_proto_rawDesc
+	file_gosdn_topology_port_proto_rawDescData []byte
 )
 
 func file_gosdn_topology_port_proto_rawDescGZIP() []byte {
 	file_gosdn_topology_port_proto_rawDescOnce.Do(func() {
-		file_gosdn_topology_port_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdn_topology_port_proto_rawDescData)
+		file_gosdn_topology_port_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gosdn_topology_port_proto_rawDesc), len(file_gosdn_topology_port_proto_rawDesc)))
 	})
 	return file_gosdn_topology_port_proto_rawDescData
 }
@@ -224,7 +223,7 @@ func file_gosdn_topology_port_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdn_topology_port_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_gosdn_topology_port_proto_rawDesc), len(file_gosdn_topology_port_proto_rawDesc)),
 			NumEnums:      0,
 			NumMessages:   2,
 			NumExtensions: 0,
@@ -235,7 +234,6 @@ func file_gosdn_topology_port_proto_init() {
 		MessageInfos:      file_gosdn_topology_port_proto_msgTypes,
 	}.Build()
 	File_gosdn_topology_port_proto = out.File
-	file_gosdn_topology_port_proto_rawDesc = nil
 	file_gosdn_topology_port_proto_goTypes = nil
 	file_gosdn_topology_port_proto_depIdxs = nil
 }
diff --git a/api/go/gosdn/topology/route.pb.go b/api/go/gosdn/topology/route.pb.go
index 9627c2df6..f4472000e 100755
--- a/api/go/gosdn/topology/route.pb.go
+++ b/api/go/gosdn/topology/route.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: gosdn/topology/route.proto
 
@@ -16,6 +16,7 @@ import (
 	_ "google.golang.org/protobuf/types/descriptorpb"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -26,15 +27,14 @@ const (
 )
 
 type Route struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Id            string                 `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	TargetIPRange string                 `protobuf:"bytes,2,opt,name=targetIPRange,proto3" json:"targetIPRange,omitempty"`
+	NextHopIP     string                 `protobuf:"bytes,3,opt,name=nextHopIP,proto3" json:"nextHopIP,omitempty"`
+	PortID        string                 `protobuf:"bytes,4,opt,name=portID,proto3" json:"portID,omitempty"`
+	Metric        string                 `protobuf:"bytes,5,opt,name=metric,proto3" json:"metric,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Id            string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	TargetIPRange string `protobuf:"bytes,2,opt,name=targetIPRange,proto3" json:"targetIPRange,omitempty"`
-	NextHopIP     string `protobuf:"bytes,3,opt,name=nextHopIP,proto3" json:"nextHopIP,omitempty"`
-	PortID        string `protobuf:"bytes,4,opt,name=portID,proto3" json:"portID,omitempty"`
-	Metric        string `protobuf:"bytes,5,opt,name=metric,proto3" json:"metric,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Route) Reset() {
@@ -103,14 +103,13 @@ func (x *Route) GetMetric() string {
 }
 
 type RoutingTable struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Id            string                 `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+	NodeID        string                 `protobuf:"bytes,2,opt,name=nodeID,proto3" json:"nodeID,omitempty"`
+	Routes        []*Route               `protobuf:"bytes,3,rep,name=routes,proto3" json:"routes,omitempty"`
+	Metadata      *conflict.Metadata     `protobuf:"bytes,4,opt,name=metadata,proto3" json:"metadata,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Id       string             `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
-	NodeID   string             `protobuf:"bytes,2,opt,name=nodeID,proto3" json:"nodeID,omitempty"`
-	Routes   []*Route           `protobuf:"bytes,3,rep,name=routes,proto3" json:"routes,omitempty"`
-	Metadata *conflict.Metadata `protobuf:"bytes,4,opt,name=metadata,proto3" json:"metadata,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *RoutingTable) Reset() {
@@ -173,7 +172,7 @@ func (x *RoutingTable) GetMetadata() *conflict.Metadata {
 
 var File_gosdn_topology_route_proto protoreflect.FileDescriptor
 
-var file_gosdn_topology_route_proto_rawDesc = []byte{
+var file_gosdn_topology_route_proto_rawDesc = string([]byte{
 	0x0a, 0x1a, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79,
 	0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x67, 0x6f,
 	0x73, 0x64, 0x6e, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x1a, 0x1c, 0x67, 0x6f,
@@ -213,16 +212,16 @@ var file_gosdn_topology_route_proto_rawDesc = []byte{
 	0x2d, 0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67, 0x6f, 0x73,
 	0x64, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f,
 	0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_gosdn_topology_route_proto_rawDescOnce sync.Once
-	file_gosdn_topology_route_proto_rawDescData = file_gosdn_topology_route_proto_rawDesc
+	file_gosdn_topology_route_proto_rawDescData []byte
 )
 
 func file_gosdn_topology_route_proto_rawDescGZIP() []byte {
 	file_gosdn_topology_route_proto_rawDescOnce.Do(func() {
-		file_gosdn_topology_route_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdn_topology_route_proto_rawDescData)
+		file_gosdn_topology_route_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gosdn_topology_route_proto_rawDesc), len(file_gosdn_topology_route_proto_rawDesc)))
 	})
 	return file_gosdn_topology_route_proto_rawDescData
 }
@@ -252,7 +251,7 @@ func file_gosdn_topology_route_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdn_topology_route_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_gosdn_topology_route_proto_rawDesc), len(file_gosdn_topology_route_proto_rawDesc)),
 			NumEnums:      0,
 			NumMessages:   2,
 			NumExtensions: 0,
@@ -263,7 +262,6 @@ func file_gosdn_topology_route_proto_init() {
 		MessageInfos:      file_gosdn_topology_route_proto_msgTypes,
 	}.Build()
 	File_gosdn_topology_route_proto = out.File
-	file_gosdn_topology_route_proto_rawDesc = nil
 	file_gosdn_topology_route_proto_goTypes = nil
 	file_gosdn_topology_route_proto_depIdxs = nil
 }
diff --git a/api/go/gosdn/topology/routingTable.pb.go b/api/go/gosdn/topology/routingTable.pb.go
index 1b9638cb3..d7b791f34 100755
--- a/api/go/gosdn/topology/routingTable.pb.go
+++ b/api/go/gosdn/topology/routingTable.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: gosdn/topology/routingTable.proto
 
@@ -16,6 +16,7 @@ import (
 	_ "google.golang.org/protobuf/types/descriptorpb"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -26,12 +27,11 @@ const (
 )
 
 type AddRoutingTableRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	RoutingTable  *RoutingTable          `protobuf:"bytes,2,opt,name=routingTable,proto3" json:"routingTable,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp    int64         `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	RoutingTable *RoutingTable `protobuf:"bytes,2,opt,name=routingTable,proto3" json:"routingTable,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *AddRoutingTableRequest) Reset() {
@@ -79,11 +79,10 @@ func (x *AddRoutingTableRequest) GetRoutingTable() *RoutingTable {
 }
 
 type AddRoutingTableResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *AddRoutingTableResponse) Reset() {
@@ -124,11 +123,10 @@ func (x *AddRoutingTableResponse) GetTimestamp() int64 {
 }
 
 type GetRoutesRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetRoutesRequest) Reset() {
@@ -169,12 +167,11 @@ func (x *GetRoutesRequest) GetTimestamp() int64 {
 }
 
 type GetRoutesResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	RoutingTables []*RoutingTable        `protobuf:"bytes,2,rep,name=routingTables,proto3" json:"routingTables,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp     int64           `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	RoutingTables []*RoutingTable `protobuf:"bytes,2,rep,name=routingTables,proto3" json:"routingTables,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetRoutesResponse) Reset() {
@@ -222,12 +219,11 @@ func (x *GetRoutesResponse) GetRoutingTables() []*RoutingTable {
 }
 
 type DeleteRoutesRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Id            string                 `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Id        string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeleteRoutesRequest) Reset() {
@@ -275,11 +271,10 @@ func (x *DeleteRoutesRequest) GetId() string {
 }
 
 type DeleteRoutesResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeleteRoutesResponse) Reset() {
@@ -321,7 +316,7 @@ func (x *DeleteRoutesResponse) GetTimestamp() int64 {
 
 var File_gosdn_topology_routingTable_proto protoreflect.FileDescriptor
 
-var file_gosdn_topology_routingTable_proto_rawDesc = []byte{
+var file_gosdn_topology_routingTable_proto_rawDesc = string([]byte{
 	0x0a, 0x21, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79,
 	0x2f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x70, 0x72,
 	0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x6c,
@@ -397,16 +392,16 @@ var file_gosdn_topology_routingTable_proto_rawDesc = []byte{
 	0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67, 0x6f, 0x73, 0x64,
 	0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x74,
 	0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_gosdn_topology_routingTable_proto_rawDescOnce sync.Once
-	file_gosdn_topology_routingTable_proto_rawDescData = file_gosdn_topology_routingTable_proto_rawDesc
+	file_gosdn_topology_routingTable_proto_rawDescData []byte
 )
 
 func file_gosdn_topology_routingTable_proto_rawDescGZIP() []byte {
 	file_gosdn_topology_routingTable_proto_rawDescOnce.Do(func() {
-		file_gosdn_topology_routingTable_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdn_topology_routingTable_proto_rawDescData)
+		file_gosdn_topology_routingTable_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gosdn_topology_routingTable_proto_rawDesc), len(file_gosdn_topology_routingTable_proto_rawDesc)))
 	})
 	return file_gosdn_topology_routingTable_proto_rawDescData
 }
@@ -448,7 +443,7 @@ func file_gosdn_topology_routingTable_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdn_topology_routingTable_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_gosdn_topology_routingTable_proto_rawDesc), len(file_gosdn_topology_routingTable_proto_rawDesc)),
 			NumEnums:      0,
 			NumMessages:   6,
 			NumExtensions: 0,
@@ -459,7 +454,6 @@ func file_gosdn_topology_routingTable_proto_init() {
 		MessageInfos:      file_gosdn_topology_routingTable_proto_msgTypes,
 	}.Build()
 	File_gosdn_topology_routingTable_proto = out.File
-	file_gosdn_topology_routingTable_proto_rawDesc = nil
 	file_gosdn_topology_routingTable_proto_goTypes = nil
 	file_gosdn_topology_routingTable_proto_depIdxs = nil
 }
diff --git a/api/go/gosdn/topology/routingTable.pb.gw.go b/api/go/gosdn/topology/routingTable.pb.gw.go
index 2b736a2f5..4bcd1b743 100755
--- a/api/go/gosdn/topology/routingTable.pb.gw.go
+++ b/api/go/gosdn/topology/routingTable.pb.gw.go
@@ -10,6 +10,7 @@ package topology
 
 import (
 	"context"
+	"errors"
 	"io"
 	"net/http"
 
@@ -24,109 +25,102 @@ import (
 )
 
 // Suppress "imported and not used" errors
-var _ codes.Code
-var _ io.Reader
-var _ status.Status
-var _ = runtime.String
-var _ = utilities.NewDoubleArray
-var _ = metadata.Join
+var (
+	_ codes.Code
+	_ io.Reader
+	_ status.Status
+	_ = errors.New
+	_ = runtime.String
+	_ = utilities.NewDoubleArray
+	_ = metadata.Join
+)
 
 func request_RoutingTableService_AddRoutingTable_0(ctx context.Context, marshaler runtime.Marshaler, client RoutingTableServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq AddRoutingTableRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq AddRoutingTableRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.AddRoutingTable(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_RoutingTableService_AddRoutingTable_0(ctx context.Context, marshaler runtime.Marshaler, server RoutingTableServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq AddRoutingTableRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq AddRoutingTableRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.AddRoutingTable(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_RoutingTableService_GetRoutes_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
-)
+var filter_RoutingTableService_GetRoutes_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
 
 func request_RoutingTableService_GetRoutes_0(ctx context.Context, marshaler runtime.Marshaler, client RoutingTableServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetRoutesRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq GetRoutesRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_RoutingTableService_GetRoutes_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.GetRoutes(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_RoutingTableService_GetRoutes_0(ctx context.Context, marshaler runtime.Marshaler, server RoutingTableServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetRoutesRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq GetRoutesRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_RoutingTableService_GetRoutes_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.GetRoutes(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_RoutingTableService_DeleteRoute_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
-)
+var filter_RoutingTableService_DeleteRoute_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
 
 func request_RoutingTableService_DeleteRoute_0(ctx context.Context, marshaler runtime.Marshaler, client RoutingTableServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeleteRoutesRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq DeleteRoutesRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_RoutingTableService_DeleteRoute_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.DeleteRoute(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_RoutingTableService_DeleteRoute_0(ctx context.Context, marshaler runtime.Marshaler, server RoutingTableServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeleteRoutesRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq DeleteRoutesRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_RoutingTableService_DeleteRoute_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.DeleteRoute(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 // RegisterRoutingTableServiceHandlerServer registers the http handlers for service RoutingTableService to "mux".
@@ -135,16 +129,13 @@ func local_request_RoutingTableService_DeleteRoute_0(ctx context.Context, marsha
 // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterRoutingTableServiceHandlerFromEndpoint instead.
 // GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
 func RegisterRoutingTableServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server RoutingTableServiceServer) error {
-
-	mux.Handle("POST", pattern_RoutingTableService_AddRoutingTable_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_RoutingTableService_AddRoutingTable_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.topology.RoutingTableService/AddRoutingTable", runtime.WithHTTPPathPattern("/routing/create"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.topology.RoutingTableService/AddRoutingTable", runtime.WithHTTPPathPattern("/routing/create"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -156,20 +147,15 @@ func RegisterRoutingTableServiceHandlerServer(ctx context.Context, mux *runtime.
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RoutingTableService_AddRoutingTable_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_RoutingTableService_GetRoutes_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_RoutingTableService_GetRoutes_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.topology.RoutingTableService/GetRoutes", runtime.WithHTTPPathPattern("/routing"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.topology.RoutingTableService/GetRoutes", runtime.WithHTTPPathPattern("/routing"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -181,20 +167,15 @@ func RegisterRoutingTableServiceHandlerServer(ctx context.Context, mux *runtime.
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RoutingTableService_GetRoutes_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_RoutingTableService_DeleteRoute_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_RoutingTableService_DeleteRoute_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.topology.RoutingTableService/DeleteRoute", runtime.WithHTTPPathPattern("/routing/delete"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.topology.RoutingTableService/DeleteRoute", runtime.WithHTTPPathPattern("/routing/delete"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -206,9 +187,7 @@ func RegisterRoutingTableServiceHandlerServer(ctx context.Context, mux *runtime.
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RoutingTableService_DeleteRoute_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
 
 	return nil
@@ -235,7 +214,6 @@ func RegisterRoutingTableServiceHandlerFromEndpoint(ctx context.Context, mux *ru
 			}
 		}()
 	}()
-
 	return RegisterRoutingTableServiceHandler(ctx, mux, conn)
 }
 
@@ -251,14 +229,11 @@ func RegisterRoutingTableServiceHandler(ctx context.Context, mux *runtime.ServeM
 // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
 // "RoutingTableServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares.
 func RegisterRoutingTableServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client RoutingTableServiceClient) error {
-
-	mux.Handle("POST", pattern_RoutingTableService_AddRoutingTable_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_RoutingTableService_AddRoutingTable_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.topology.RoutingTableService/AddRoutingTable", runtime.WithHTTPPathPattern("/routing/create"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.topology.RoutingTableService/AddRoutingTable", runtime.WithHTTPPathPattern("/routing/create"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -269,18 +244,13 @@ func RegisterRoutingTableServiceHandlerClient(ctx context.Context, mux *runtime.
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RoutingTableService_AddRoutingTable_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_RoutingTableService_GetRoutes_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_RoutingTableService_GetRoutes_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.topology.RoutingTableService/GetRoutes", runtime.WithHTTPPathPattern("/routing"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.topology.RoutingTableService/GetRoutes", runtime.WithHTTPPathPattern("/routing"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -291,18 +261,13 @@ func RegisterRoutingTableServiceHandlerClient(ctx context.Context, mux *runtime.
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RoutingTableService_GetRoutes_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_RoutingTableService_DeleteRoute_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_RoutingTableService_DeleteRoute_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.topology.RoutingTableService/DeleteRoute", runtime.WithHTTPPathPattern("/routing/delete"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.topology.RoutingTableService/DeleteRoute", runtime.WithHTTPPathPattern("/routing/delete"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -313,26 +278,19 @@ func RegisterRoutingTableServiceHandlerClient(ctx context.Context, mux *runtime.
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_RoutingTableService_DeleteRoute_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
 	return nil
 }
 
 var (
 	pattern_RoutingTableService_AddRoutingTable_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"routing", "create"}, ""))
-
-	pattern_RoutingTableService_GetRoutes_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"routing"}, ""))
-
-	pattern_RoutingTableService_DeleteRoute_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"routing", "delete"}, ""))
+	pattern_RoutingTableService_GetRoutes_0       = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"routing"}, ""))
+	pattern_RoutingTableService_DeleteRoute_0     = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"routing", "delete"}, ""))
 )
 
 var (
 	forward_RoutingTableService_AddRoutingTable_0 = runtime.ForwardResponseMessage
-
-	forward_RoutingTableService_GetRoutes_0 = runtime.ForwardResponseMessage
-
-	forward_RoutingTableService_DeleteRoute_0 = runtime.ForwardResponseMessage
+	forward_RoutingTableService_GetRoutes_0       = runtime.ForwardResponseMessage
+	forward_RoutingTableService_DeleteRoute_0     = runtime.ForwardResponseMessage
 )
diff --git a/api/go/gosdn/topology/topology.pb.go b/api/go/gosdn/topology/topology.pb.go
index 6d85ea4ad..073a288f8 100755
--- a/api/go/gosdn/topology/topology.pb.go
+++ b/api/go/gosdn/topology/topology.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: gosdn/topology/topology.proto
 
@@ -15,6 +15,7 @@ import (
 	_ "google.golang.org/protobuf/types/descriptorpb"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -25,11 +26,10 @@ const (
 )
 
 type Topology struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Links         []*Link                `protobuf:"bytes,1,rep,name=links,proto3" json:"links,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Links []*Link `protobuf:"bytes,1,rep,name=links,proto3" json:"links,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *Topology) Reset() {
@@ -70,12 +70,11 @@ func (x *Topology) GetLinks() []*Link {
 }
 
 type AddLinkRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Link          *Link                  `protobuf:"bytes,2,opt,name=link,proto3" json:"link,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Link      *Link `protobuf:"bytes,2,opt,name=link,proto3" json:"link,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *AddLinkRequest) Reset() {
@@ -123,11 +122,10 @@ func (x *AddLinkRequest) GetLink() *Link {
 }
 
 type AddLinkResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *AddLinkResponse) Reset() {
@@ -168,11 +166,10 @@ func (x *AddLinkResponse) GetTimestamp() int64 {
 }
 
 type GetTopologyRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetTopologyRequest) Reset() {
@@ -213,12 +210,11 @@ func (x *GetTopologyRequest) GetTimestamp() int64 {
 }
 
 type GetTopologyResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Toplogy       *Topology              `protobuf:"bytes,2,opt,name=toplogy,proto3" json:"toplogy,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64     `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Toplogy   *Topology `protobuf:"bytes,2,opt,name=toplogy,proto3" json:"toplogy,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *GetTopologyResponse) Reset() {
@@ -266,12 +262,11 @@ func (x *GetTopologyResponse) GetToplogy() *Topology {
 }
 
 type UpdateLinkRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Link          *Link                  `protobuf:"bytes,2,opt,name=link,proto3" json:"link,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Link      *Link `protobuf:"bytes,2,opt,name=link,proto3" json:"link,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *UpdateLinkRequest) Reset() {
@@ -319,11 +314,10 @@ func (x *UpdateLinkRequest) GetLink() *Link {
 }
 
 type UpdateLinkResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *UpdateLinkResponse) Reset() {
@@ -364,12 +358,11 @@ func (x *UpdateLinkResponse) GetTimestamp() int64 {
 }
 
 type DeleteLinkRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	Id            string                 `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
-	Id        string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeleteLinkRequest) Reset() {
@@ -417,11 +410,10 @@ func (x *DeleteLinkRequest) GetId() string {
 }
 
 type DeleteLinkResponse struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Timestamp     int64                  `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
 	unknownFields protoimpl.UnknownFields
-
-	Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *DeleteLinkResponse) Reset() {
@@ -463,7 +455,7 @@ func (x *DeleteLinkResponse) GetTimestamp() int64 {
 
 var File_gosdn_topology_topology_proto protoreflect.FileDescriptor
 
-var file_gosdn_topology_topology_proto_rawDesc = []byte{
+var file_gosdn_topology_topology_proto_rawDesc = string([]byte{
 	0x0a, 0x1d, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79,
 	0x2f, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
 	0x0e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x1a,
@@ -552,16 +544,16 @@ var file_gosdn_topology_topology_proto_rawDesc = []byte{
 	0x2f, 0x64, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70, 0x69,
 	0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x74, 0x6f, 0x70, 0x6f, 0x6c, 0x6f,
 	0x67, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_gosdn_topology_topology_proto_rawDescOnce sync.Once
-	file_gosdn_topology_topology_proto_rawDescData = file_gosdn_topology_topology_proto_rawDesc
+	file_gosdn_topology_topology_proto_rawDescData []byte
 )
 
 func file_gosdn_topology_topology_proto_rawDescGZIP() []byte {
 	file_gosdn_topology_topology_proto_rawDescOnce.Do(func() {
-		file_gosdn_topology_topology_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdn_topology_topology_proto_rawDescData)
+		file_gosdn_topology_topology_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gosdn_topology_topology_proto_rawDesc), len(file_gosdn_topology_topology_proto_rawDesc)))
 	})
 	return file_gosdn_topology_topology_proto_rawDescData
 }
@@ -610,7 +602,7 @@ func file_gosdn_topology_topology_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdn_topology_topology_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_gosdn_topology_topology_proto_rawDesc), len(file_gosdn_topology_topology_proto_rawDesc)),
 			NumEnums:      0,
 			NumMessages:   9,
 			NumExtensions: 0,
@@ -621,7 +613,6 @@ func file_gosdn_topology_topology_proto_init() {
 		MessageInfos:      file_gosdn_topology_topology_proto_msgTypes,
 	}.Build()
 	File_gosdn_topology_topology_proto = out.File
-	file_gosdn_topology_topology_proto_rawDesc = nil
 	file_gosdn_topology_topology_proto_goTypes = nil
 	file_gosdn_topology_topology_proto_depIdxs = nil
 }
diff --git a/api/go/gosdn/topology/topology.pb.gw.go b/api/go/gosdn/topology/topology.pb.gw.go
index 93edbd2fd..d4587d504 100755
--- a/api/go/gosdn/topology/topology.pb.gw.go
+++ b/api/go/gosdn/topology/topology.pb.gw.go
@@ -10,6 +10,7 @@ package topology
 
 import (
 	"context"
+	"errors"
 	"io"
 	"net/http"
 
@@ -24,135 +25,126 @@ import (
 )
 
 // Suppress "imported and not used" errors
-var _ codes.Code
-var _ io.Reader
-var _ status.Status
-var _ = runtime.String
-var _ = utilities.NewDoubleArray
-var _ = metadata.Join
+var (
+	_ codes.Code
+	_ io.Reader
+	_ status.Status
+	_ = errors.New
+	_ = runtime.String
+	_ = utilities.NewDoubleArray
+	_ = metadata.Join
+)
 
 func request_TopologyService_AddLink_0(ctx context.Context, marshaler runtime.Marshaler, client TopologyServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq AddLinkRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq AddLinkRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.AddLink(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_TopologyService_AddLink_0(ctx context.Context, marshaler runtime.Marshaler, server TopologyServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq AddLinkRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq AddLinkRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.AddLink(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_TopologyService_GetTopology_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
-)
+var filter_TopologyService_GetTopology_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
 
 func request_TopologyService_GetTopology_0(ctx context.Context, marshaler runtime.Marshaler, client TopologyServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetTopologyRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq GetTopologyRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_TopologyService_GetTopology_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.GetTopology(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_TopologyService_GetTopology_0(ctx context.Context, marshaler runtime.Marshaler, server TopologyServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq GetTopologyRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq GetTopologyRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_TopologyService_GetTopology_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.GetTopology(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 func request_TopologyService_UpdateLink_0(ctx context.Context, marshaler runtime.Marshaler, client TopologyServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq UpdateLinkRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq UpdateLinkRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.UpdateLink(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_TopologyService_UpdateLink_0(ctx context.Context, marshaler runtime.Marshaler, server TopologyServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq UpdateLinkRequest
-	var metadata runtime.ServerMetadata
-
-	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
+	var (
+		protoReq UpdateLinkRequest
+		metadata runtime.ServerMetadata
+	)
+	if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.UpdateLink(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
-var (
-	filter_TopologyService_DeleteLink_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
-)
+var filter_TopologyService_DeleteLink_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
 
 func request_TopologyService_DeleteLink_0(ctx context.Context, marshaler runtime.Marshaler, client TopologyServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeleteLinkRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq DeleteLinkRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_TopologyService_DeleteLink_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := client.DeleteLink(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
 	return msg, metadata, err
-
 }
 
 func local_request_TopologyService_DeleteLink_0(ctx context.Context, marshaler runtime.Marshaler, server TopologyServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
-	var protoReq DeleteLinkRequest
-	var metadata runtime.ServerMetadata
-
+	var (
+		protoReq DeleteLinkRequest
+		metadata runtime.ServerMetadata
+	)
 	if err := req.ParseForm(); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
 	if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_TopologyService_DeleteLink_0); err != nil {
 		return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
 	}
-
 	msg, err := server.DeleteLink(ctx, &protoReq)
 	return msg, metadata, err
-
 }
 
 // RegisterTopologyServiceHandlerServer registers the http handlers for service TopologyService to "mux".
@@ -161,16 +153,13 @@ func local_request_TopologyService_DeleteLink_0(ctx context.Context, marshaler r
 // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterTopologyServiceHandlerFromEndpoint instead.
 // GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
 func RegisterTopologyServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server TopologyServiceServer) error {
-
-	mux.Handle("POST", pattern_TopologyService_AddLink_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_TopologyService_AddLink_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.topology.TopologyService/AddLink", runtime.WithHTTPPathPattern("/topology/create"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.topology.TopologyService/AddLink", runtime.WithHTTPPathPattern("/topology/create"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -182,20 +171,15 @@ func RegisterTopologyServiceHandlerServer(ctx context.Context, mux *runtime.Serv
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_TopologyService_AddLink_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_TopologyService_GetTopology_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_TopologyService_GetTopology_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.topology.TopologyService/GetTopology", runtime.WithHTTPPathPattern("/topology"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.topology.TopologyService/GetTopology", runtime.WithHTTPPathPattern("/topology"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -207,20 +191,15 @@ func RegisterTopologyServiceHandlerServer(ctx context.Context, mux *runtime.Serv
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_TopologyService_GetTopology_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_TopologyService_UpdateLink_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_TopologyService_UpdateLink_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.topology.TopologyService/UpdateLink", runtime.WithHTTPPathPattern("/topology/update"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.topology.TopologyService/UpdateLink", runtime.WithHTTPPathPattern("/topology/update"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -232,20 +211,15 @@ func RegisterTopologyServiceHandlerServer(ctx context.Context, mux *runtime.Serv
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_TopologyService_UpdateLink_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_TopologyService_DeleteLink_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_TopologyService_DeleteLink_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		var stream runtime.ServerTransportStream
 		ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.topology.TopologyService/DeleteLink", runtime.WithHTTPPathPattern("/topology/delete"))
+		annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gosdn.topology.TopologyService/DeleteLink", runtime.WithHTTPPathPattern("/topology/delete"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -257,9 +231,7 @@ func RegisterTopologyServiceHandlerServer(ctx context.Context, mux *runtime.Serv
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_TopologyService_DeleteLink_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
 
 	return nil
@@ -286,7 +258,6 @@ func RegisterTopologyServiceHandlerFromEndpoint(ctx context.Context, mux *runtim
 			}
 		}()
 	}()
-
 	return RegisterTopologyServiceHandler(ctx, mux, conn)
 }
 
@@ -302,14 +273,11 @@ func RegisterTopologyServiceHandler(ctx context.Context, mux *runtime.ServeMux,
 // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
 // "TopologyServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares.
 func RegisterTopologyServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client TopologyServiceClient) error {
-
-	mux.Handle("POST", pattern_TopologyService_AddLink_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_TopologyService_AddLink_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.topology.TopologyService/AddLink", runtime.WithHTTPPathPattern("/topology/create"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.topology.TopologyService/AddLink", runtime.WithHTTPPathPattern("/topology/create"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -320,18 +288,13 @@ func RegisterTopologyServiceHandlerClient(ctx context.Context, mux *runtime.Serv
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_TopologyService_AddLink_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("GET", pattern_TopologyService_GetTopology_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodGet, pattern_TopologyService_GetTopology_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.topology.TopologyService/GetTopology", runtime.WithHTTPPathPattern("/topology"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.topology.TopologyService/GetTopology", runtime.WithHTTPPathPattern("/topology"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -342,18 +305,13 @@ func RegisterTopologyServiceHandlerClient(ctx context.Context, mux *runtime.Serv
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_TopologyService_GetTopology_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("POST", pattern_TopologyService_UpdateLink_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodPost, pattern_TopologyService_UpdateLink_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.topology.TopologyService/UpdateLink", runtime.WithHTTPPathPattern("/topology/update"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.topology.TopologyService/UpdateLink", runtime.WithHTTPPathPattern("/topology/update"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -364,18 +322,13 @@ func RegisterTopologyServiceHandlerClient(ctx context.Context, mux *runtime.Serv
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_TopologyService_UpdateLink_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
-	mux.Handle("DELETE", pattern_TopologyService_DeleteLink_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+	mux.Handle(http.MethodDelete, pattern_TopologyService_DeleteLink_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
 		ctx, cancel := context.WithCancel(req.Context())
 		defer cancel()
 		inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
-		var err error
-		var annotatedContext context.Context
-		annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gosdn.topology.TopologyService/DeleteLink", runtime.WithHTTPPathPattern("/topology/delete"))
+		annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gosdn.topology.TopologyService/DeleteLink", runtime.WithHTTPPathPattern("/topology/delete"))
 		if err != nil {
 			runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
 			return
@@ -386,30 +339,21 @@ func RegisterTopologyServiceHandlerClient(ctx context.Context, mux *runtime.Serv
 			runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
 			return
 		}
-
 		forward_TopologyService_DeleteLink_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
 	})
-
 	return nil
 }
 
 var (
-	pattern_TopologyService_AddLink_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"topology", "create"}, ""))
-
+	pattern_TopologyService_AddLink_0     = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"topology", "create"}, ""))
 	pattern_TopologyService_GetTopology_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"topology"}, ""))
-
-	pattern_TopologyService_UpdateLink_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"topology", "update"}, ""))
-
-	pattern_TopologyService_DeleteLink_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"topology", "delete"}, ""))
+	pattern_TopologyService_UpdateLink_0  = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"topology", "update"}, ""))
+	pattern_TopologyService_DeleteLink_0  = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"topology", "delete"}, ""))
 )
 
 var (
-	forward_TopologyService_AddLink_0 = runtime.ForwardResponseMessage
-
+	forward_TopologyService_AddLink_0     = runtime.ForwardResponseMessage
 	forward_TopologyService_GetTopology_0 = runtime.ForwardResponseMessage
-
-	forward_TopologyService_UpdateLink_0 = runtime.ForwardResponseMessage
-
-	forward_TopologyService_DeleteLink_0 = runtime.ForwardResponseMessage
+	forward_TopologyService_UpdateLink_0  = runtime.ForwardResponseMessage
+	forward_TopologyService_DeleteLink_0  = runtime.ForwardResponseMessage
 )
diff --git a/api/go/gosdn/transport/transport.pb.go b/api/go/gosdn/transport/transport.pb.go
index 24ebcfbe0..22768e44c 100755
--- a/api/go/gosdn/transport/transport.pb.go
+++ b/api/go/gosdn/transport/transport.pb.go
@@ -1,6 +1,6 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.35.1
+// 	protoc-gen-go v1.36.4
 // 	protoc        (unknown)
 // source: gosdn/transport/transport.proto
 
@@ -14,6 +14,7 @@ import (
 	_ "google.golang.org/protobuf/types/descriptorpb"
 	reflect "reflect"
 	sync "sync"
+	unsafe "unsafe"
 )
 
 const (
@@ -24,20 +25,19 @@ const (
 )
 
 type TransportOption struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Address  string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
-	Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
-	Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"`
-	Tls      bool   `protobuf:"varint,4,opt,name=tls,proto3" json:"tls,omitempty"`
-	// Types that are assignable to TransportOption:
+	state    protoimpl.MessageState `protogen:"open.v1"`
+	Address  string                 `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
+	Username string                 `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
+	Password string                 `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"`
+	Tls      bool                   `protobuf:"varint,4,opt,name=tls,proto3" json:"tls,omitempty"`
+	// Types that are valid to be assigned to TransportOption:
 	//
 	//	*TransportOption_GnmiTransportOption
 	//	*TransportOption_RestconfTransportOption
 	TransportOption isTransportOption_TransportOption `protobuf_oneof:"transport_option"`
 	Type            southbound.Type                   `protobuf:"varint,7,opt,name=type,proto3,enum=gosdn.southbound.Type" json:"type,omitempty"`
+	unknownFields   protoimpl.UnknownFields
+	sizeCache       protoimpl.SizeCache
 }
 
 func (x *TransportOption) Reset() {
@@ -98,23 +98,27 @@ func (x *TransportOption) GetTls() bool {
 	return false
 }
 
-func (m *TransportOption) GetTransportOption() isTransportOption_TransportOption {
-	if m != nil {
-		return m.TransportOption
+func (x *TransportOption) GetTransportOption() isTransportOption_TransportOption {
+	if x != nil {
+		return x.TransportOption
 	}
 	return nil
 }
 
 func (x *TransportOption) GetGnmiTransportOption() *GnmiTransportOption {
-	if x, ok := x.GetTransportOption().(*TransportOption_GnmiTransportOption); ok {
-		return x.GnmiTransportOption
+	if x != nil {
+		if x, ok := x.TransportOption.(*TransportOption_GnmiTransportOption); ok {
+			return x.GnmiTransportOption
+		}
 	}
 	return nil
 }
 
 func (x *TransportOption) GetRestconfTransportOption() *RestconfTransportOption {
-	if x, ok := x.GetTransportOption().(*TransportOption_RestconfTransportOption); ok {
-		return x.RestconfTransportOption
+	if x != nil {
+		if x, ok := x.TransportOption.(*TransportOption_RestconfTransportOption); ok {
+			return x.RestconfTransportOption
+		}
 	}
 	return nil
 }
@@ -143,14 +147,13 @@ func (*TransportOption_GnmiTransportOption) isTransportOption_TransportOption()
 func (*TransportOption_RestconfTransportOption) isTransportOption_TransportOption() {}
 
 type GnmiTransportOption struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Compression     string            `protobuf:"bytes,1,opt,name=compression,proto3" json:"compression,omitempty"`
-	GrpcDialOptions map[string]string `protobuf:"bytes,2,rep,name=grpc_dial_options,json=grpcDialOptions,proto3" json:"grpc_dial_options,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
-	Token           string            `protobuf:"bytes,3,opt,name=token,proto3" json:"token,omitempty"`
-	Encoding        gnmi.Encoding     `protobuf:"varint,4,opt,name=encoding,proto3,enum=gnmi.Encoding" json:"encoding,omitempty"`
+	state           protoimpl.MessageState `protogen:"open.v1"`
+	Compression     string                 `protobuf:"bytes,1,opt,name=compression,proto3" json:"compression,omitempty"`
+	GrpcDialOptions map[string]string      `protobuf:"bytes,2,rep,name=grpc_dial_options,json=grpcDialOptions,proto3" json:"grpc_dial_options,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+	Token           string                 `protobuf:"bytes,3,opt,name=token,proto3" json:"token,omitempty"`
+	Encoding        gnmi.Encoding          `protobuf:"varint,4,opt,name=encoding,proto3,enum=gnmi.Encoding" json:"encoding,omitempty"`
+	unknownFields   protoimpl.UnknownFields
+	sizeCache       protoimpl.SizeCache
 }
 
 func (x *GnmiTransportOption) Reset() {
@@ -212,9 +215,9 @@ func (x *GnmiTransportOption) GetEncoding() gnmi.Encoding {
 }
 
 type RestconfTransportOption struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
+	state         protoimpl.MessageState `protogen:"open.v1"`
 	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
 }
 
 func (x *RestconfTransportOption) Reset() {
@@ -249,7 +252,7 @@ func (*RestconfTransportOption) Descriptor() ([]byte, []int) {
 
 var File_gosdn_transport_transport_proto protoreflect.FileDescriptor
 
-var file_gosdn_transport_transport_proto_rawDesc = []byte{
+var file_gosdn_transport_transport_proto_rawDesc = string([]byte{
 	0x0a, 0x1f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72,
 	0x74, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74,
 	0x6f, 0x12, 0x0f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f,
@@ -309,16 +312,16 @@ var file_gosdn_transport_transport_proto_rawDesc = []byte{
 	0x74, 0x2f, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x67,
 	0x6f, 0x73, 0x64, 0x6e, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x62, 0x06,
 	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
+})
 
 var (
 	file_gosdn_transport_transport_proto_rawDescOnce sync.Once
-	file_gosdn_transport_transport_proto_rawDescData = file_gosdn_transport_transport_proto_rawDesc
+	file_gosdn_transport_transport_proto_rawDescData []byte
 )
 
 func file_gosdn_transport_transport_proto_rawDescGZIP() []byte {
 	file_gosdn_transport_transport_proto_rawDescOnce.Do(func() {
-		file_gosdn_transport_transport_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdn_transport_transport_proto_rawDescData)
+		file_gosdn_transport_transport_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_gosdn_transport_transport_proto_rawDesc), len(file_gosdn_transport_transport_proto_rawDesc)))
 	})
 	return file_gosdn_transport_transport_proto_rawDescData
 }
@@ -358,7 +361,7 @@ func file_gosdn_transport_transport_proto_init() {
 	out := protoimpl.TypeBuilder{
 		File: protoimpl.DescBuilder{
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdn_transport_transport_proto_rawDesc,
+			RawDescriptor: unsafe.Slice(unsafe.StringData(file_gosdn_transport_transport_proto_rawDesc), len(file_gosdn_transport_transport_proto_rawDesc)),
 			NumEnums:      0,
 			NumMessages:   4,
 			NumExtensions: 0,
@@ -369,7 +372,6 @@ func file_gosdn_transport_transport_proto_init() {
 		MessageInfos:      file_gosdn_transport_transport_proto_msgTypes,
 	}.Build()
 	File_gosdn_transport_transport_proto = out.File
-	file_gosdn_transport_transport_proto_rawDesc = nil
 	file_gosdn_transport_transport_proto_goTypes = nil
 	file_gosdn_transport_transport_proto_depIdxs = nil
 }
diff --git a/api/openapiv2/gosdn_northbound.swagger.json b/api/openapiv2/gosdn_northbound.swagger.json
index faefcc2b9..a000de65c 100755
--- a/api/openapiv2/gosdn_northbound.swagger.json
+++ b/api/openapiv2/gosdn_northbound.swagger.json
@@ -709,6 +709,37 @@
         ]
       }
     },
+    "/plugins": {
+      "get": {
+        "operationId": "PluginInternalService_GetAvailablePlugins",
+        "responses": {
+          "200": {
+            "description": "A successful response.",
+            "schema": {
+              "$ref": "#/definitions/gosdnplugin_registryGetResponse"
+            }
+          },
+          "default": {
+            "description": "An unexpected error response.",
+            "schema": {
+              "$ref": "#/definitions/googlerpcStatus"
+            }
+          }
+        },
+        "parameters": [
+          {
+            "name": "timestamp",
+            "in": "query",
+            "required": false,
+            "type": "string",
+            "format": "int64"
+          }
+        ],
+        "tags": [
+          "PluginInternalService"
+        ]
+      }
+    },
     "/pnd/{pid}": {
       "get": {
         "summary": "Allows to request a specific Principal Network Domain.",
diff --git a/api/proto/gosdn/networkelement/networkelement.proto b/api/proto/gosdn/networkelement/networkelement.proto
index b2a14817b..e893c00f2 100755
--- a/api/proto/gosdn/networkelement/networkelement.proto
+++ b/api/proto/gosdn/networkelement/networkelement.proto
@@ -407,4 +407,4 @@ message SubscribePathRequest {
 message SubscribePathResponse {
   int64 timestamp = 1; // Timestamp in nanoseconds since Epoch.
   repeated gnmi.Notification mne_notification = 2;
-}
+}
\ No newline at end of file
diff --git a/api/proto/gosdn/plugin-internal/plugin-internal.proto b/api/proto/gosdn/plugin-internal/plugin-internal.proto
index 85b721572..70ad2e22f 100755
--- a/api/proto/gosdn/plugin-internal/plugin-internal.proto
+++ b/api/proto/gosdn/plugin-internal/plugin-internal.proto
@@ -4,21 +4,21 @@ package gosdn.plugin_internal;
 
 import "buf/validate/validate.proto";
 import "gosdn/plugin-registry/plugin-registry.proto";
+import "google/api/annotations.proto";
+
 
 option go_package = "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/plugin-internal";
 
 service PluginInternalService {
   rpc AvailablePlugins(GetAvailablePluginsRequest) returns (gosdn.plugin_registry.GetResponse);
   rpc GetPluginSchema(GetPluginSchemaRequest) returns (stream PluginSchemaPayload);
+  rpc GetAvailablePlugins(GetAvailablePluginsRequest) returns (gosdn.plugin_registry.GetResponse) {
+    option (google.api.http) = {get: "/plugins"};
 }
-
-message GetAvailablePluginsRequest {
-  int64 timestamp = 1;
 }
 
-message GetAvailablePluginsResponse {
+message GetAvailablePluginsRequest {
   int64 timestamp = 1;
-  repeated gosdn.plugin_registry.Plugin plugins = 2;
 }
 
 message GetPluginSchemaRequest {
@@ -29,3 +29,8 @@ message GetPluginSchemaRequest {
 message PluginSchemaPayload {
   bytes chunk = 1;
 }
+
+message GetAvailablePluginsResponse {
+  int64 timestamp = 1; // Timestamp in nanoseconds since Epoch.
+  repeated gosdn.plugin_registry.Plugin plugins = 2;
+}
\ No newline at end of file
diff --git a/api/proto/gosdn/plugin-registry/plugin-registry.proto b/api/proto/gosdn/plugin-registry/plugin-registry.proto
index ee4040c58..1210ab99c 100755
--- a/api/proto/gosdn/plugin-registry/plugin-registry.proto
+++ b/api/proto/gosdn/plugin-registry/plugin-registry.proto
@@ -4,6 +4,8 @@ package gosdn.plugin_registry;
 
 import "google/protobuf/timestamp.proto";
 import "buf/validate/validate.proto";
+import "google/api/annotations.proto";
+
 
 option go_package = "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/plugin-registry";
 
@@ -64,3 +66,12 @@ message Manifest {
   string author = 3;
   string version = 4;
 }
+
+message GetAvailablePluginsResponse {
+  int64 timestamp = 1; // Timestamp in nanoseconds since Epoch.
+  repeated gosdn.plugin_registry.Plugin plugins = 2;
+}
+
+message GetAvailablePluginsRequest {
+  int64 timestamp = 1;
+}
\ No newline at end of file
diff --git a/api/proto/gosdn/plugin/plugin.proto b/api/proto/gosdn/plugin/plugin.proto
index 80b6bec34..6d7ca8447 100755
--- a/api/proto/gosdn/plugin/plugin.proto
+++ b/api/proto/gosdn/plugin/plugin.proto
@@ -4,8 +4,11 @@ package gosdn.plugin;
 
 import "github.com/openconfig/gnmi/proto/gnmi/gnmi.proto";
 import "buf/validate/validate.proto";
+import "google/api/annotations.proto";
+
 
 import "gosdn/networkelement/networkelement.proto";
+import "gosdn/plugin-registry/plugin-registry.proto";
 
 
 option go_package = "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/plugin";
@@ -20,6 +23,7 @@ service Plugin {
     rpc SchemaTreeGzip(SchemaTreeGzipRequest) returns (stream Payload);
     rpc ValidateChange(ValidateChangeRequest) returns (ValidateChangeResponse);
     rpc PruneConfigFalse(PruneConfigFalseRequest) returns (PruneConfigFalseResponse);
+    rpc GetAvailablePlugins(GetAvailablePluginsRequest) returns (gosdn.plugin_registry.GetResponse);
 }
 
 message UnmarshalRequest {
@@ -99,3 +103,7 @@ message SchemaTreeGzipRequest {
 message Payload {
   bytes chunk = 1;
 }
+
+message GetAvailablePluginsRequest {
+    int64 timestamp = 1;
+  }
\ No newline at end of file
diff --git a/controller/controller.go b/controller/controller.go
index 32adf3586..3b339bd52 100755
--- a/controller/controller.go
+++ b/controller/controller.go
@@ -349,6 +349,7 @@ func ensureAdminRoleExists() error {
 			"/gosdn.networkelement.NetworkElementService/ParseYang",
 			"/gosdn.plugin_internal.PluginInternalService/AvailablePlugins",
 			"/gosdn.plugin_internal.PluginInternalService/GetPluginSchema",
+			"/gosdn.plugin_internal.PluginInternalService/GetAvailablePlugins",
 			"/gosdn.app.AppService/Register",
 			"/gosdn.app.AppService/Deregister",
 			"/gosdn.configurationmanagement.ConfigurationManagementService/ExportSDNConfig",
diff --git a/controller/http.go b/controller/http.go
index 394b7a0b0..684b8f83f 100755
--- a/controller/http.go
+++ b/controller/http.go
@@ -16,6 +16,7 @@ import (
 	"google.golang.org/grpc/status"
 
 	mnegw "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/networkelement"
+	plg "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/plugin-internal"
 	pgw "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/pnd"
 	agw "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/rbac"
 	tgw "code.fbi.h-da.de/danet/gosdn/api/go/gosdn/topology"
@@ -85,6 +86,11 @@ func setupHttpServer() error {
 		return err
 	}
 
+	err = plg.RegisterPluginInternalServiceHandlerFromEndpoint(ctx, mux, *grpcServerEndpoint, opts)
+	if err != nil {
+		return err
+	}
+
 	// Set the HTTP server of core to the new server
 	c.httpServer = &http.Server{Addr: ":8080",
 		Handler:           mux,
diff --git a/controller/northbound/server/plugin.go b/controller/northbound/server/plugin.go
index 3338520da..8e73994d3 100755
--- a/controller/northbound/server/plugin.go
+++ b/controller/northbound/server/plugin.go
@@ -55,6 +55,22 @@ func (pis *PluginInternalServer) AvailablePlugins(ctx context.Context, request *
 	return pis.pluginRegistryClient.GetAll(ctx, getAllRequest)
 }
 
+func (pis *PluginInternalServer) GetAvailablePlugins(ctx context.Context, request *pipb.GetAvailablePluginsRequest) (*rpb.GetResponse, error) {
+	ctx, cancel := context.WithTimeout(ctx, time.Minute*1)
+	defer cancel()
+
+	if err := pis.protoValidator.Validate(request); err != nil {
+		return nil, status.Errorf(codes.Aborted, "%v", err)
+	}
+
+	getAllRequest := &rpb.GetAllRequest{
+		Timestamp: time.Now().UnixNano(),
+	}
+
+	return pis.pluginRegistryClient.GetAll(ctx, getAllRequest)
+
+}
+
 func (pis *PluginInternalServer) GetPluginSchema(request *pipb.GetPluginSchemaRequest, stream pipb.PluginInternalService_GetPluginSchemaServer) error {
 	labels := prometheus.Labels{"service": "plugin", "rpc": "get plugin schema"}
 	start := metrics.StartHook(labels, grpcRequestsTotal)
diff --git a/react-ui/src/components/login/view/login.view.tsx b/react-ui/src/components/login/view/login.view.tsx
index 62c84eeb8..6b782e877 100755
--- a/react-ui/src/components/login/view/login.view.tsx
+++ b/react-ui/src/components/login/view/login.view.tsx
@@ -31,7 +31,7 @@ const LoginView: React.FC<BasicProp> = () => {
                 <Image src={logo} alt="logo" height={150} />
             </Row>
             <Row className="mt-2 justify-content-center">
-                <Col md={6} sm={10} className="c-box p-4">
+                <Col md={6} sm={10} className="c-box p-4 bg-white">
                     <h1 className="text-center h2">goSDN - Web</h1>
 
                     {handleErrorMessageRendering(invalidForm, invalidCredentials)}
-- 
GitLab


From be88b3acf29154393287329d562f09fb9dae247e Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Thu, 6 Feb 2025 08:08:40 +0000
Subject: [PATCH 72/79] [renovate] Update module github.com/spf13/pflag to
 v1.0.6

See merge request danet/gosdn!1185

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 2 +-
 go.sum | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/go.mod b/go.mod
index 85321aae1..a1da60ddb 100644
--- a/go.mod
+++ b/go.mod
@@ -18,7 +18,7 @@ require (
 	github.com/sethvargo/go-password v0.3.1
 	github.com/sirupsen/logrus v1.9.3
 	github.com/spf13/cobra v1.8.1
-	github.com/spf13/pflag v1.0.5
+	github.com/spf13/pflag v1.0.6
 	github.com/spf13/viper v1.19.0
 	github.com/stretchr/objx v0.5.2 // indirect
 	github.com/stretchr/testify v1.10.0
diff --git a/go.sum b/go.sum
index 3c9264734..c37cab057 100644
--- a/go.sum
+++ b/go.sum
@@ -378,6 +378,8 @@ github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
 github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
+github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
 github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
 github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
-- 
GitLab


From 7b2c10af091052557e2635c5a37b09395f16e10e Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Thu, 6 Feb 2025 08:20:31 +0000
Subject: [PATCH 73/79] [renovate] Update module github.com/openconfig/gnmi to
 v0.13.0

See merge request danet/gosdn!1186

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 6 ++++--
 go.sum | 2 ++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/go.mod b/go.mod
index a1da60ddb..966dfa1b4 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,8 @@
 module code.fbi.h-da.de/danet/gosdn
 
-go 1.23
+go 1.23.4
+
+toolchain go1.23.6
 
 require (
 	github.com/aristanetworks/goarista v0.0.0-20250108234106-1f88a86e2265
@@ -10,7 +12,7 @@ require (
 	github.com/google/uuid v1.6.0
 	github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.0
 	github.com/mitchellh/go-homedir v1.1.0
-	github.com/openconfig/gnmi v0.12.0
+	github.com/openconfig/gnmi v0.13.0
 	github.com/openconfig/goyang v1.6.0
 	github.com/openconfig/ygot v0.29.20
 	github.com/prometheus/client_golang v1.20.5
diff --git a/go.sum b/go.sum
index c37cab057..d6017dd0b 100644
--- a/go.sum
+++ b/go.sum
@@ -296,6 +296,8 @@ github.com/openconfig/gnmi v0.11.0 h1:H7pLIb/o3xObu3+x0Fv9DCK7TH3FUh7mNwbYe+34hF
 github.com/openconfig/gnmi v0.11.0/go.mod h1:9oJSQPPCpNvfMRj8e4ZoLVAw4wL8HyxXbiDlyuexCGU=
 github.com/openconfig/gnmi v0.12.0 h1:aPkmcX9pdcz6QqsBsXXg5UQooqhnmlHD3JtdtvtzmaU=
 github.com/openconfig/gnmi v0.12.0/go.mod h1:5a/cIOZevJLfJgd1qWkgYROE8xfgEbaSJXpdD8xk/LQ=
+github.com/openconfig/gnmi v0.13.0 h1:4aVopzMZVYtfrRqlpDqM0liutE+3/AiDMzNtI2r7em4=
+github.com/openconfig/gnmi v0.13.0/go.mod h1:YJwAQ6qkU06TU/g4ZqjxSkajOm0adoBK86/s6w0ow3w=
 github.com/openconfig/goyang v0.0.0-20200115183954-d0a48929f0ea/go.mod h1:dhXaV0JgHJzdrHi2l+w0fZrwArtXL7jEFoiqLEdmkvU=
 github.com/openconfig/goyang v1.6.0 h1:JjnPbLY1/y28VyTO67LsEV0TaLWNiZyDcsppGq4F4is=
 github.com/openconfig/goyang v1.6.0/go.mod h1:sdNZi/wdTZyLNBNfgLzmmbi7kISm7FskMDKKzMY+x1M=
-- 
GitLab


From f3c33dc7a2c7fe8dbb168d4218a5c1d73ea9391a Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Thu, 6 Feb 2025 08:33:14 +0000
Subject: [PATCH 74/79] [renovate] Update renovate/renovate Docker tag to
 v39.161.4

See merge request danet/gosdn!1188

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 .gitlab/ci/.renovate.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab/ci/.renovate.yml b/.gitlab/ci/.renovate.yml
index 9142bc5b3..b8ccc7b58 100644
--- a/.gitlab/ci/.renovate.yml
+++ b/.gitlab/ci/.renovate.yml
@@ -1,7 +1,7 @@
 renovate:
     stage: tools
 
-    image: renovate/renovate:39.140.0
+    image: renovate/renovate:39.161.4
 
     variables:
         LOG_LEVEL: debug
-- 
GitLab


From c8bb3c3411ac87a4c8c2ec35bf6a1f66496bf1c1 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Thu, 6 Feb 2025 08:45:56 +0000
Subject: [PATCH 75/79] [renovate] Update module github.com/lesismal/nbio to
 v1.6.2

See merge request danet/gosdn!1190

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 4 ++--
 go.sum | 4 ++++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/go.mod b/go.mod
index 966dfa1b4..1dafbc585 100644
--- a/go.mod
+++ b/go.mod
@@ -92,7 +92,7 @@ require (
 	github.com/bufbuild/protovalidate-go v0.8.2
 	github.com/hashicorp/go-multierror v1.1.1
 	github.com/hashicorp/go-plugin v1.4.10
-	github.com/lesismal/nbio v1.6.1
+	github.com/lesismal/nbio v1.6.2
 	go.mongodb.org/mongo-driver v1.17.2
 	google.golang.org/genproto/googleapis/api v0.0.0-20250127172529-29210b9bc287
 )
@@ -110,7 +110,7 @@ require (
 	github.com/hashicorp/errwrap v1.1.0 // indirect
 	github.com/hashicorp/go-hclog v1.5.0 // indirect
 	github.com/hashicorp/yamux v0.1.1 // indirect
-	github.com/lesismal/llib v1.2.0 // indirect
+	github.com/lesismal/llib v1.2.1 // indirect
 	github.com/lithammer/fuzzysearch v1.1.8 // indirect
 	github.com/mitchellh/go-testing-interface v1.14.1 // indirect
 	github.com/moby/patternmatcher v0.5.0 // indirect
diff --git a/go.sum b/go.sum
index d6017dd0b..ac1cefc35 100644
--- a/go.sum
+++ b/go.sum
@@ -234,6 +234,8 @@ github.com/lesismal/llib v1.1.13 h1:+w1+t0PykXpj2dXQck0+p6vdC9/mnbEXHgUy/HXDGfE=
 github.com/lesismal/llib v1.1.13/go.mod h1:70tFXXe7P1FZ02AU9l8LgSOK7d7sRrpnkUr3rd3gKSg=
 github.com/lesismal/llib v1.2.0 h1:76mtWL87Y2XTYSoBXNFMBmUZY6igHbQZW48c0gx32Hc=
 github.com/lesismal/llib v1.2.0/go.mod h1:70tFXXe7P1FZ02AU9l8LgSOK7d7sRrpnkUr3rd3gKSg=
+github.com/lesismal/llib v1.2.1 h1:Cz/ZoCYhsLAr3A67K2DlHnsp/O7G2j+eTWmiKUu3WuE=
+github.com/lesismal/llib v1.2.1/go.mod h1:70tFXXe7P1FZ02AU9l8LgSOK7d7sRrpnkUr3rd3gKSg=
 github.com/lesismal/nbio v1.5.10 h1:k9O6a2bG+eBJn4ed94d918AB55QxF0KEj0OHKLCppJQ=
 github.com/lesismal/nbio v1.5.10/go.mod h1:QsxE0fKFe1PioyjuHVDn2y8ktYK7xv9MFbpkoRFj8vI=
 github.com/lesismal/nbio v1.5.11 h1:MVjrzcej4NSJQMRT+S0dPZvVaiFUHD1JWnvr+FHIHOo=
@@ -244,6 +246,8 @@ github.com/lesismal/nbio v1.6.0 h1:QqkFifnJjcUOzMT8edybXiBa1qlvueYEszy4ZCVroDM=
 github.com/lesismal/nbio v1.6.0/go.mod h1:Ah601gkk8O67QG8uAEz6qP6JHZY4oG0FdWllj3R2Ouc=
 github.com/lesismal/nbio v1.6.1 h1:PUMHD7NpE41KFKmPXS4bmEasAgNTUaD2YR7EGkt8X7s=
 github.com/lesismal/nbio v1.6.1/go.mod h1:Ah601gkk8O67QG8uAEz6qP6JHZY4oG0FdWllj3R2Ouc=
+github.com/lesismal/nbio v1.6.2 h1:vcjLDtF8mqQisbX9dYiShs+If7q+G4XXvjBKry51lZY=
+github.com/lesismal/nbio v1.6.2/go.mod h1:4Nz9So5nq8P4NpLT41M2WKZg9ZkiX1Ai7nH2XJagnmU=
 github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4=
 github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4=
 github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
-- 
GitLab


From 62fe5d0e6a137a2235d6df6d3e9346fd879cae91 Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Thu, 6 Feb 2025 09:04:23 +0000
Subject: [PATCH 76/79] [renovate] Update
 google.golang.org/genproto/googleapis/api digest to 7023788

See merge request danet/gosdn!1191

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 2 +-
 go.sum | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/go.mod b/go.mod
index 1dafbc585..6657a574f 100644
--- a/go.mod
+++ b/go.mod
@@ -94,7 +94,7 @@ require (
 	github.com/hashicorp/go-plugin v1.4.10
 	github.com/lesismal/nbio v1.6.2
 	go.mongodb.org/mongo-driver v1.17.2
-	google.golang.org/genproto/googleapis/api v0.0.0-20250127172529-29210b9bc287
+	google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489
 )
 
 require (
diff --git a/go.sum b/go.sum
index ac1cefc35..a62826022 100644
--- a/go.sum
+++ b/go.sum
@@ -646,6 +646,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250122153221-138b5a5a4fd4 h1:
 google.golang.org/genproto/googleapis/api v0.0.0-20250122153221-138b5a5a4fd4/go.mod h1:AfA77qWLcidQWywD0YgqfpJzf50w2VjzBml3TybHeJU=
 google.golang.org/genproto/googleapis/api v0.0.0-20250127172529-29210b9bc287 h1:A2ni10G3UlplFrWdCDJTl7D7mJ7GSRm37S+PDimaKRw=
 google.golang.org/genproto/googleapis/api v0.0.0-20250127172529-29210b9bc287/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4=
+google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489 h1:fCuMM4fowGzigT89NCIsW57Pk9k2D12MMi2ODn+Nk+o=
+google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed h1:J6izYgfBXAI3xTKLgxzTmUltdYaLsuBxFCgDHWJ/eXg=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
-- 
GitLab


From 95eb2f006a5969bfbeb974009a39eaa89cf2fc3c Mon Sep 17 00:00:00 2001
From: renovate_bot
 <group_8045_bot_08826d7c233c44435d2dae5013b96892@noreply.code.fbi.h-da.de>
Date: Thu, 6 Feb 2025 09:28:55 +0000
Subject: [PATCH 77/79] [renovate] Update module golang.org/x/sync to v0.11.0

See merge request danet/gosdn!1192

Co-authored-by: Renovate Bot <renovate@danet.fbi.h-da.de>
---
 go.mod | 2 +-
 go.sum | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/go.mod b/go.mod
index 6657a574f..75b8c2010 100644
--- a/go.mod
+++ b/go.mod
@@ -25,7 +25,7 @@ require (
 	github.com/stretchr/objx v0.5.2 // indirect
 	github.com/stretchr/testify v1.10.0
 	go.mongodb.org/mongo-driver/v2 v2.0.0
-	golang.org/x/sync v0.10.0
+	golang.org/x/sync v0.11.0
 	google.golang.org/grpc v1.70.0
 	google.golang.org/protobuf v1.36.4
 	gopkg.in/yaml.v3 v3.0.1
diff --git a/go.sum b/go.sum
index a62826022..6c670172e 100644
--- a/go.sum
+++ b/go.sum
@@ -520,6 +520,8 @@ golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
 golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
 golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
+golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-- 
GitLab


From 7f7c60d6202ad82cc0cf5560415b4ef28b27af27 Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@stud.h-da.de>
Date: Thu, 6 Feb 2025 19:05:00 +0100
Subject: [PATCH 78/79] (ui): added 'add_device' functionality

---
 react-ui/package.json                         |   1 +
 react-ui/src/.prettierrc                      |   4 +
 .../devices/reducer/plugin.reducer.ts         |  75 +----
 .../devices/routines/mne.routine.ts           |   1 -
 .../devices/routines/plugin.routine.ts        |  36 +++
 .../devices/view/device.view.list.tsx         | 186 +++++++-----
 .../components/devices/view/device.view.tsx   | 146 +++++----
 .../devices/view/subcomponent/modal.view.tsx  | 279 ++++++++++--------
 .../devices/view_model/device.viewmodel.ts    |  21 +-
 .../devices/view_model/modal.viewmodel.ts     |  92 +++++-
 .../src/i18n/locales/en/translations.json     |  46 +++
 react-ui/src/shared/api/api.ts                |  24 ++
 react-ui/src/stores/persist.store.ts          |   4 +
 react-ui/yarn.lock                            |   5 +
 14 files changed, 578 insertions(+), 342 deletions(-)
 create mode 100644 react-ui/src/.prettierrc
 create mode 100644 react-ui/src/components/devices/routines/plugin.routine.ts

diff --git a/react-ui/package.json b/react-ui/package.json
index 8bdbbfa50..76af9e08b 100755
--- a/react-ui/package.json
+++ b/react-ui/package.json
@@ -26,6 +26,7 @@
         "react-dom": "^18.3.1",
         "react-error-boundary": "^4.1.2",
         "react-grid-layout": "^1.5.0",
+        "react-hook-form": "^7.54.2",
         "react-i18next": "^15.0.0",
         "react-loading-skeleton": "^3.5.0",
         "react-redux": "^9.1.2",
diff --git a/react-ui/src/.prettierrc b/react-ui/src/.prettierrc
new file mode 100644
index 000000000..222861c34
--- /dev/null
+++ b/react-ui/src/.prettierrc
@@ -0,0 +1,4 @@
+{
+  "tabWidth": 2,
+  "useTabs": false
+}
diff --git a/react-ui/src/components/devices/reducer/plugin.reducer.ts b/react-ui/src/components/devices/reducer/plugin.reducer.ts
index 1a09876fe..f11f24477 100644
--- a/react-ui/src/components/devices/reducer/plugin.reducer.ts
+++ b/react-ui/src/components/devices/reducer/plugin.reducer.ts
@@ -1,15 +1,10 @@
 import {
     NetworkelementFlattenedManagedNetworkElement,
     NetworkelementManagedNetworkElement,
-    PndPrincipalNetworkDomain
+    PluginRegistryPlugin
 } from '@api/api'
 import { createSlice, PayloadAction } from '@reduxjs/toolkit'
-import { refreshUpdateTimer } from '@shared/reducer/routine.reducer'
-import { Category, CategoryType } from '@shared/types/category.type'
-import { REHYDRATE } from 'redux-persist'
-import { RootState } from 'src/stores'
 import '../routines/index'
-import { startListening } from '/src/stores/middleware/listener.middleware'
 
 export type Device = NetworkelementFlattenedManagedNetworkElement
 
@@ -19,14 +14,11 @@ interface SelectedObject {
     json: JSON | null
 }
 
-export interface DeviceSliceState {
-    devices: Device[]
-    pnds: PndPrincipalNetworkDomain[]
-
-    selected: SelectedObject | null
+export interface PluginSliceState {
+    plugins: Array<PluginRegistryPlugin>
 }
 
-const initialState: DeviceSliceState = {
+const initialState: PluginSliceState = {
     plugins: [],
 }
 
@@ -37,63 +29,18 @@ interface SetSelectedDeviceType {
     }
 }
 
-const deviceSlice = createSlice({
+const pluginSlice = createSlice({
     name: 'plugins',
     initialState,
     reducers: {
-        setPlugins: (state, action: PayloadAction<Plugin[] | undefined>) => {
-            state.devices = action.payload || []
+        setPlugins: (state, action: PayloadAction<PluginRegistryPlugin[] | undefined>) => {
+            state.plugins = action.payload || []
         },
     },
 })
 
-export const { setDevices, setSelectedDevice, setSelectedMne, setSelectedJson, setPnds } =
-    deviceSlice.actions
-
-export default deviceSlice.reducer
-export const deviceReducerPath = deviceSlice.reducerPath
-
-// add default selected device if no selected device is set
-startListening({
-    predicate: (action) => setDevices.match(action),
-    effect: async (action, listenerApi) => {
-        const { device: state } = listenerApi.getOriginalState() as RootState
-        if (state.selected) {
-            return
-        }
-
-        // if there are no devices available do set null
-        const device = action.payload?.[0] || null
-        listenerApi.dispatch(setSelectedDevice({ device } as SetSelectedDeviceType))
-    },
-})
-
-startListening({
-    predicate: (action) => setSelectedMne.match(action),
-    effect: async (action, listenerApi) => {
-        listenerApi.dispatch(refreshUpdateTimer(Category.TAB as CategoryType))
-    },
-})
+export const { setPlugins } =
+    pluginSlice.actions
 
-startListening({
-    predicate: (action) => setDevices.match(action),
-    effect: async (action, listenerApi) => {
-        listenerApi.dispatch(refreshUpdateTimer(Category.DEVICE as CategoryType))
-    },
-})
-
-/**
- * On startup reset the selected device 
- */
-startListening({
-    predicate: ({ type }: any) => type === REHYDRATE,
-    effect: async (_, listenerApi) => {
-        const { device: state } = listenerApi.getState() as RootState
-        const device = state.selected?.device
-        if (!device) {
-            return
-        }
-
-        listenerApi.dispatch(setSelectedDevice({ device, options: { bypassCheck: true } } as SetSelectedDeviceType))
-    },
-})
\ No newline at end of file
+export default pluginSlice.reducer
+export const pluginReducerPath = pluginSlice.reducerPath
diff --git a/react-ui/src/components/devices/routines/mne.routine.ts b/react-ui/src/components/devices/routines/mne.routine.ts
index 292869307..967da2615 100755
--- a/react-ui/src/components/devices/routines/mne.routine.ts
+++ b/react-ui/src/components/devices/routines/mne.routine.ts
@@ -13,7 +13,6 @@ import { startListening } from '../../../stores/middleware/listener.middleware'
 
 export const FETCH_MNE_ACTION = 'subscription/device/fetchSelectedMNE'
 
-
 /**
  * #0
  * Trigger fetch MNE (#1)
diff --git a/react-ui/src/components/devices/routines/plugin.routine.ts b/react-ui/src/components/devices/routines/plugin.routine.ts
new file mode 100644
index 000000000..ece4608f7
--- /dev/null
+++ b/react-ui/src/components/devices/routines/plugin.routine.ts
@@ -0,0 +1,36 @@
+import { PluginInternalServiceGetAvailablePluginsApiArg, api } from "@api/api"
+import { warnMessage } from "@helper/debug"
+import { createAsyncThunk } from "@reduxjs/toolkit"
+import { RootState } from "src/stores"
+import { setPlugins } from "../reducer/plugin.reducer"
+
+const FETCH_PLUGIN_ACTION = 'subscription/plugin/fetchPlugins'
+
+
+export const fetchPluginsThunk = createAsyncThunk(
+    FETCH_PLUGIN_ACTION,
+    async (_, thunkApi) => {
+        const { user } = thunkApi.getState() as RootState
+
+        if (!user.user?.roles) {
+            warnMessage('Plugin fetch was triggered but user data is not presence')
+            return
+        }
+
+        const payload: PluginInternalServiceGetAvailablePluginsApiArg = {
+            timestamp: new Date().getTime().toString(),
+        }
+
+
+        const plugins = await thunkApi.dispatch(api.endpoints.pluginInternalServiceGetAvailablePlugins.initiate(payload))
+
+        if (plugins.error || !plugins.data?.plugins) {
+            warnMessage('Plugin fetch returned an error: ' + plugins.error)
+            return
+        }
+
+        thunkApi.dispatch(
+            setPlugins(plugins.data?.plugins)
+        )
+    }
+)
\ No newline at end of file
diff --git a/react-ui/src/components/devices/view/device.view.list.tsx b/react-ui/src/components/devices/view/device.view.list.tsx
index 53f1580d1..868f26959 100755
--- a/react-ui/src/components/devices/view/device.view.list.tsx
+++ b/react-ui/src/components/devices/view/device.view.list.tsx
@@ -1,94 +1,122 @@
 import { insertMarkTags } from "@helper/text";
 import { useAppSelector } from "@hooks";
-import DOMPurify from 'dompurify';
-import { RefObject, useCallback, useRef } from 'react';
-import { Col, OverlayTrigger, Row, Tooltip } from 'react-bootstrap';
+import DOMPurify from "dompurify";
+import { RefObject, useCallback, useRef } from "react";
+import { Col, OverlayTrigger, Row, Tooltip } from "react-bootstrap";
 import { useTranslation } from "react-i18next";
 import { Device } from "../reducer/device.reducer";
 import { useDeviceTableViewModel } from "../view_model/device.list.viewmodel";
 
 const cropUUID = (uuid: string): string => {
-    return uuid.substring(0, 3) + "..." + uuid.substring(uuid.length - 3, uuid.length);
+  return (
+    uuid.substring(0, 3) + "..." + uuid.substring(uuid.length - 3, uuid.length)
+  );
 };
 
-export const DeviceList = ({ searchRef }: { searchRef: RefObject<HTMLInputElement> }) => {
-    const { devices, pnds, selected: selectedDevice } = useAppSelector(state => state.device);
-    const { t } = useTranslation('common');
-    const listRef = useRef<HTMLDivElement>(null);
-    const { dispatchDevice } = useDeviceTableViewModel(searchRef, listRef);
+export const DeviceList = ({
+  searchRef,
+}: {
+  searchRef: RefObject<HTMLInputElement>;
+}) => {
+  const {
+    devices,
+    pnds,
+    selected: selectedDevice,
+  } = useAppSelector((state) => state.device);
+  const { t } = useTranslation("common");
+  const listRef = useRef<HTMLDivElement>(null);
+  const { dispatchDevice } = useDeviceTableViewModel(searchRef, listRef);
 
-    const handleItemClick = useCallback((device: Device) => {
-        dispatchDevice(device)
-    }, []);
+  const handleItemClick = useCallback((device: Device) => {
+    dispatchDevice(device);
+  }, []);
 
-    const getDeviceList = useCallback(() => {
-        const search = searchRef?.current?.value;
-        let filtered = devices;
+  const getDeviceList = useCallback(() => {
+    const search = searchRef?.current?.value;
+    let filtered = devices;
 
-        if (search) {
-            filtered = devices.filter((device) => {
-                const user = pnds.find(pnd => pnd.id === device.pid);
-                return device.id?.includes(search) ||
-                    device.name?.includes(search) ||
-                    user?.name?.includes(search);
-            });
-        }
+    if (search) {
+      filtered = devices.filter((device) => {
+        const user = pnds.find((pnd) => pnd.id === device.pid);
+        return (
+          device.id?.includes(search) ||
+          device.name?.includes(search) ||
+          user?.name?.includes(search)
+        );
+      });
+    }
 
-        return filtered.map((device) => {
-            const user = pnds.find(pnd => pnd.id === device.pid);
-            const username = user?.name || '';
-            const deviceId = device.id!;
-            const croppedId = cropUUID(deviceId);
-            const devicename = device.name || '';
-            const isSelected = selectedDevice?.device.id === deviceId;
+    return filtered.map((device) => {
+      const user = pnds.find((pnd) => pnd.id === device.pid);
+      const username = user?.name || "";
+      const deviceId = device.id!;
+      const croppedId = cropUUID(deviceId);
+      const devicename = device.name || "";
+      const isSelected = selectedDevice?.device.id === deviceId;
 
-            return (
-                <div
-                    key={deviceId}
-                    className={`border-bottom border-primary p-2 transitions ${isSelected && 'bg-gradient-fade py-2'} ${!isSelected && 'text-disabled disabled-hover'}`}
-                    onClick={() => handleItemClick(device)}
-                >
-                    <Row
-                        className="align-items-center clickable"
-                        onClick={() => handleItemClick(device)}
-                    >
-                        <Col xs={12} sm={5} >
-                            <span dangerouslySetInnerHTML={{
-                                __html: search ? insertMarkTags(devicename, search) : DOMPurify.sanitize(devicename)
-                            }} />
-                        </Col>
-                        <Col xs={12} sm={3} >
-                            <OverlayTrigger overlay={<Tooltip id={deviceId}>{deviceId}</Tooltip>}>
-                                <span className="text-gray-500" dangerouslySetInnerHTML={{
-                                    __html: search ? insertMarkTags(croppedId, search) : DOMPurify.sanitize(croppedId)
-                                }} />
-                            </OverlayTrigger>
-                        </Col>
-                        <Col xs={12} sm={4} >
-                            <span className="text-gray-500" dangerouslySetInnerHTML={{
-                                __html: search ? insertMarkTags(username, search) : DOMPurify.sanitize(username)
-                            }} />
-                        </Col>
-                    </Row>
-                </div>
-            );
-        });
-    }, [devices, searchRef, pnds, selectedDevice, handleItemClick]);
-
-    return (
-        <div className="rounded border border-primary mt-2">
-            <Row className="border-bottom border-primary px-2 py-2 mx-0">
-                <Col xs={12} sm={5} >
-                    <span className="font-medium">{t('device.table.header.name')}</span>
-                </Col>
-                <Col xs={12} sm={3} >
-                    <span className="font-medium">{t('device.table.header.uuid')}</span>
-                </Col>
-                <Col xs={12} sm={4} >
-                    <span className="font-medium">{t('device.table.header.user')}</span>
-                </Col>
-            </Row>
-            <div ref={listRef}>{getDeviceList()}</div>
+      return (
+        <div
+          key={deviceId}
+          className={`border-bottom border-primary p-2 transitions ${isSelected && "bg-gradient-fade py-2"} ${!isSelected && "text-disabled disabled-hover"}`}
+          onClick={() => handleItemClick(device)}
+        >
+          <Row
+            className="align-items-center clickable"
+            onClick={() => handleItemClick(device)}
+          >
+            <Col xs={12} sm={5}>
+              <span
+                dangerouslySetInnerHTML={{
+                  __html: search
+                    ? insertMarkTags(devicename, search)
+                    : DOMPurify.sanitize(devicename),
+                }}
+              />
+            </Col>
+            <Col xs={12} sm={3}>
+              <OverlayTrigger
+                overlay={<Tooltip id={deviceId}>{deviceId}</Tooltip>}
+              >
+                <span
+                  className="text-gray-500"
+                  dangerouslySetInnerHTML={{
+                    __html: search
+                      ? insertMarkTags(croppedId, search)
+                      : DOMPurify.sanitize(croppedId),
+                  }}
+                />
+              </OverlayTrigger>
+            </Col>
+            <Col xs={12} sm={4}>
+              <span
+                className="text-gray-500"
+                dangerouslySetInnerHTML={{
+                  __html: search
+                    ? insertMarkTags(username, search)
+                    : DOMPurify.sanitize(username),
+                }}
+              />
+            </Col>
+          </Row>
         </div>
-    );
-};
\ No newline at end of file
+      );
+    });
+  }, [devices, searchRef, pnds, selectedDevice, handleItemClick]);
+
+  return (
+    <div className="rounded border border-primary mt-2">
+      <Row className="border-bottom border-primary px-2 py-2 mx-0">
+        <Col xs={12} sm={5}>
+          <span className="font-medium">{t("device.table.header.name")}</span>
+        </Col>
+        <Col xs={12} sm={3}>
+          <span className="font-medium">{t("device.table.header.uuid")}</span>
+        </Col>
+        <Col xs={12} sm={4}>
+          <span className="font-medium">{t("device.table.header.user")}</span>
+        </Col>
+      </Row>
+      <div ref={listRef}>{getDeviceList()}</div>
+    </div>
+  );
+};
diff --git a/react-ui/src/components/devices/view/device.view.tsx b/react-ui/src/components/devices/view/device.view.tsx
index 290697ac6..814f51db1 100755
--- a/react-ui/src/components/devices/view/device.view.tsx
+++ b/react-ui/src/components/devices/view/device.view.tsx
@@ -1,69 +1,91 @@
-import { faCircleInfo, faPlus, faServer, faSliders } from '@fortawesome/free-solid-svg-icons';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { GridLayout } from '@layout/grid.layout/grid.layout';
-import { GridBox } from '@shared/components/box/gridBox.view';
-import { JsonViewer } from '@shared/components/json_viewer/view/json_viewer.view';
-import { useRef } from 'react';
-import { Button, Col, Form, Row } from 'react-bootstrap';
-import { useTranslation } from 'react-i18next';
-import { useDeviceViewModel } from '../view_model/device.viewmodel';
-import './device.scss';
-import { DeviceList } from './device.view.list';
-import { DeviceListCollapsable } from './subcomponent/device.view.list-detail';
+import {
+  faCircleInfo,
+  faPlus,
+  faServer,
+  faSliders,
+} from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { GridLayout } from "@layout/grid.layout/grid.layout";
+import { GridBox } from "@shared/components/box/gridBox.view";
+import { JsonViewer } from "@shared/components/json_viewer/view/json_viewer.view";
+import { useRef } from "react";
+import { Button, Col, Form, Row } from "react-bootstrap";
+import { useTranslation } from "react-i18next";
+import { useDeviceViewModel } from "../view_model/device.viewmodel";
+import "./device.scss";
+import { DeviceList } from "./device.view.list";
+import { DeviceListCollapsable } from "./subcomponent/device.view.list-detail";
+import AddDeviceModal from "./subcomponent/modal.view";
 
 const DeviceView = () => {
-    const { t } = useTranslation('common');
-    const searchRef = useRef<HTMLInputElement>(null);
-    const { jsonYang } = useDeviceViewModel();
+  const { t } = useTranslation("common");
+  const searchRef = useRef<HTMLInputElement>(null);
+  const { jsonYang, openAddModal, closeModal, addModal } = useDeviceViewModel();
 
-    return (
-        <GridLayout>
-            <>
-                <div key="device-list">
-                    <GridBox title={t("device.box.list.title")} title_icon={faServer}>
-                        <Row className="mb-3 align-items-center">
-                            <Col xs={12} md={6} lg={8}>
-                                <Form.Group controlId='device.search'>
-                                    <Form.Control type="text" placeholder={t('device.search.placeholder')} ref={searchRef} />
-                                </Form.Group>
-                            </Col>
-                            <Col xs={12} md={6} lg={4} className='mt-3 mt-md-0 text-md-end'>
-                                <Button variant='primary::button' className='btn-primary-button'>
-                                    <FontAwesomeIcon icon={faPlus} className='me-2' />
-                                    {t('device.add_device_button')}
-                                </Button>
-                            </Col>
-                        </Row>
-                        <Row>
-                            <Col xs={12} className='h-auto'>
-                                <DeviceList searchRef={searchRef} />
-                            </Col>
-                        </Row>
-                    </GridBox>
-                </div>
+  return (
+    <GridLayout>
+      <>
+        <div key="device-list">
+          <GridBox title={t("device.box.list.title")} title_icon={faServer}>
+            <Row className="mb-3 align-items-center">
+              <Col xs={12} md={6} lg={8}>
+                <Form.Group controlId="device.search">
+                  <Form.Control
+                    type="text"
+                    placeholder={t("device.search.placeholder")}
+                    ref={searchRef}
+                  />
+                </Form.Group>
+              </Col>
+              <Col xs={12} md={6} lg={4} className="mt-3 mt-md-0 text-md-end">
+                <Button
+                  variant="primary::button"
+                  className="btn-primary-button"
+                  onClick={() => openAddModal()}
+                >
+                  <FontAwesomeIcon icon={faPlus} className="me-2" />
+                  {t("device.add_device_button")}
+                </Button>
 
-                <div key="device-metadata">
-                    <GridBox title={t("device.box.information.title")} title_icon={faCircleInfo}>
-                        <Row>
-                            <Col xs={12} >
-                                <DeviceListCollapsable search={searchRef.current?.value || ''} />
-                            </Col>
-                        </Row>
-                    </GridBox>
-                </div>
+                <AddDeviceModal show={addModal} onHide={() => closeModal()} />
+              </Col>
+            </Row>
+            <Row>
+              <Col xs={12} className="h-auto">
+                <DeviceList searchRef={searchRef} />
+              </Col>
+            </Row>
+          </GridBox>
+        </div>
 
-                <div key="device-details">
-                    <GridBox title={t('device.box.configuration.title')} title_icon={faSliders}>
-                        <Row>
-                            <Col xs={12}>
-                                {jsonYang && <JsonViewer json={jsonYang} />}
-                            </Col>
-                        </Row>
-                    </GridBox>
-                </div>
-            </>
-        </GridLayout>
-    );
+        <div key="device-metadata">
+          <GridBox
+            title={t("device.box.information.title")}
+            title_icon={faCircleInfo}
+          >
+            <Row>
+              <Col xs={12}>
+                <DeviceListCollapsable
+                  search={searchRef.current?.value || ""}
+                />
+              </Col>
+            </Row>
+          </GridBox>
+        </div>
+
+        <div key="device-details">
+          <GridBox
+            title={t("device.box.configuration.title")}
+            title_icon={faSliders}
+          >
+            <Row>
+              <Col xs={12}>{jsonYang && <JsonViewer json={jsonYang} />}</Col>
+            </Row>
+          </GridBox>
+        </div>
+      </>
+    </GridLayout>
+  );
 };
 
-export default DeviceView;
\ No newline at end of file
+export default DeviceView;
diff --git a/react-ui/src/components/devices/view/subcomponent/modal.view.tsx b/react-ui/src/components/devices/view/subcomponent/modal.view.tsx
index d798e7ade..fd5936412 100644
--- a/react-ui/src/components/devices/view/subcomponent/modal.view.tsx
+++ b/react-ui/src/components/devices/view/subcomponent/modal.view.tsx
@@ -1,141 +1,162 @@
-import { NetworkelementAddListRequest, useNetworkElementServiceAddListMutation } from '@api/api';
-import React, { useState } from 'react';
-import { Button, Form, Modal } from 'react-bootstrap';
+import { useModalViewModel } from "@component/devices/view_model/modal.viewmodel";
+import { useAppSelector } from "@hooks";
+import React from "react";
+import { Alert, Button, Form, Modal } from "react-bootstrap";
+import { useTranslation } from "react-i18next";
 
 interface AddDeviceModalProps {
-    show: boolean;
-    onHide: () => void;
-}
-
-interface FormData {
-    address: '',
-    mneName: '',
-    transportOption: undefined,
-    gnmiSubscribePaths: [],
+  show: boolean;
+  onHide: () => void;
 }
 
 const AddDeviceModal: React.FC<AddDeviceModalProps> = ({ show, onHide }) => {
-    const [addNetworkElement] = useNetworkElementServiceAddListMutation();
-    const [formData, setFormData] = useState<FormData>({
-        address: '',
-        mneName: '',
-        transportOption: undefined,
-        gnmiSubscribePaths: [],
-    });
-
-    const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
-        const { name, value } = e.target;
-        setFormData(prev => ({
-            ...prev,
-            [name]: value
-        }));
-    };
-
-    const handleSubmit = async (e: React.FormEvent) => {
-        e.preventDefault();
+  const { loading, register, handleSubmit, errors } = useModalViewModel({
+    hide: onHide,
+  });
+  const { plugins } = useAppSelector((state) => state.plugin);
+  const { t } = useTranslation("common");
 
-        const request: NetworkelementAddListRequest = {
-            timestamp: Date.now().toString(), // Convert to nanoseconds if needed
-            mne: [formData],
-            pid: formData.pid
-        };
+  return (
+    <Modal show={show} onHide={onHide} centered size="lg">
+      <Modal.Header closeButton>
+        <Modal.Title>{t("device.add_device.title")}</Modal.Title>
+      </Modal.Header>
+      <Modal.Body>
+        {errors.root && (
+          <Alert variant="danger" className="mt-3">
+            {errors.root.message || t("device.add_device.error")}
+          </Alert>
+        )}
+        <Form onSubmit={handleSubmit}>
+          <Form.Group className="mb-3">
+            <Form.Label>
+              {t("device.add_device.fields.mne_name.label")}
+            </Form.Label>
+            <Form.Control
+              type="text"
+              placeholder={t("device.add_device.fields.mne_name.placeholder")}
+              isInvalid={!!errors.mneName}
+              {...register("mneName", {
+                required: t("device.add_device.fields.mne_name.required"),
+              })}
+            />
+            <Form.Control.Feedback type="invalid">
+              {errors.mneName?.message}
+            </Form.Control.Feedback>
+          </Form.Group>
+          <Form.Group className="mb-3">
+            <Form.Label>
+              {t("device.add_device.fields.address.label")}
+            </Form.Label>
+            <Form.Control
+              type="text"
+              placeholder={t("device.add_device.fields.address.placeholder")}
+              isInvalid={!!errors.address}
+              {...register("transportOption.address", {
+                required: t("device.add_device.fields.address.required"),
+              })}
+            />
+            <Form.Control.Feedback type="invalid">
+              {errors.address?.message}
+            </Form.Control.Feedback>
+          </Form.Group>
 
-        try {
-            await addNetworkElement({ networkelementAddListRequest: request });
-            handleReset();
-            // You might want to add a success notification here
-        } catch (error) {
-            console.error('Failed to add device:', error);
-            // You might want to add an error notification here
-        }
-    };
+          <Form.Group className="mb-3">
+            <Form.Label>
+              {t("device.add_device.fields.plugin.label")}
+            </Form.Label>
+            <Form.Control
+              as="select"
+              isInvalid={!!errors.pluginId}
+              {...register("pluginId", {
+                required: t("device.add_device.fields.plugin.required"),
+              })}
+            >
+              <option value="">
+                {t("device.add_device.fields.plugin.placeholder")}
+              </option>
+              {plugins.map((plugin) => (
+                <option key={plugin.id} value={plugin.id}>
+                  {plugin.manifest?.name}
+                </option>
+              ))}
+            </Form.Control>
+            <Form.Control.Feedback type="invalid">
+              {errors.pluginId?.message}
+            </Form.Control.Feedback>
+          </Form.Group>
 
-    const handleReset = () => {
-        setFormData({
-            address: '',
-            pid: '',
-            pluginId: '',
-            mneName: '',
-            transportOption: undefined,
-            gnmiSubscribePaths: [],
-            mneId: ''
-        });
-        onHide();
-    };
+          <Form.Group className="mb-3">
+            <Form.Check
+              type="checkbox"
+              label={t("device.add_device.fields.tls.label")}
+              {...register("transportOption.tls")}
+            />
+          </Form.Group>
 
-    return (
-        <Modal show={show} onHide={handleReset} centered>
-            <Modal.Header closeButton>
-                <Modal.Title>Add New Device</Modal.Title>
-            </Modal.Header>
-            <Form onSubmit={handleSubmit}>
-                <Modal.Body>
-                    <Form.Group className="mb-3">
-                        <Form.Label>Address</Form.Label>
-                        <Form.Control
-                            type="text"
-                            name="address"
-                            value={formData.address}
-                            onChange={handleInputChange}
-                            placeholder="Enter device address"
-                        />
-                    </Form.Group>
+          <h5 className="mt-4">
+            {t("device.add_device.fields.credentials.title")}
+          </h5>
+          <Form.Group className="mb-3">
+            <Form.Label>
+              {t("device.add_device.fields.credentials.username.label")}
+            </Form.Label>
+            <Form.Control
+              type="text"
+              placeholder={t(
+                "device.add_device.fields.credentials.username.placeholder",
+              )}
+              isInvalid={!!errors.transportOption?.username}
+              {...register("transportOption.username", {
+                required: t(
+                  "device.add_device.fields.credentials.username.required",
+                ),
+              })}
+            />
+            <Form.Control.Feedback type="invalid">
+              {errors.transportOption?.username?.message}
+            </Form.Control.Feedback>
+          </Form.Group>
 
-                    <Form.Group className="mb-3">
-                        <Form.Label>PID</Form.Label>
-                        <Form.Control
-                            type="text"
-                            name="pid"
-                            value={formData.pid}
-                            onChange={handleInputChange}
-                            placeholder="Enter PID"
-                        />
-                    </Form.Group>
+          <Form.Group className="mb-3">
+            <Form.Label>
+              {t("device.add_device.fields.credentials.password.label")}
+            </Form.Label>
+            <Form.Control
+              type="password"
+              placeholder={t(
+                "device.add_device.fields.credentials.password.placeholder",
+              )}
+              isInvalid={!!errors.transportOption?.password}
+              {...register("transportOption.password", {
+                required: t(
+                  "device.add_device.fields.credentials.password.required",
+                ),
+              })}
+            />
+            <Form.Control.Feedback type="invalid">
+              {errors.transportOption?.password?.message}
+            </Form.Control.Feedback>
+          </Form.Group>
 
-                    <Form.Group className="mb-3">
-                        <Form.Label>Plugin ID</Form.Label>
-                        <Form.Control
-                            type="text"
-                            name="pluginId"
-                            value={formData.pluginId}
-                            onChange={handleInputChange}
-                            placeholder="Enter plugin ID"
-                        />
-                    </Form.Group>
-
-                    <Form.Group className="mb-3">
-                        <Form.Label>MNE Name</Form.Label>
-                        <Form.Control
-                            type="text"
-                            name="mneName"
-                            value={formData.mneName}
-                            onChange={handleInputChange}
-                            placeholder="Enter MNE name"
-                        />
-                    </Form.Group>
-
-                    <Form.Group className="mb-3">
-                        <Form.Label>MNE ID</Form.Label>
-                        <Form.Control
-                            type="text"
-                            name="mneId"
-                            value={formData.mneId}
-                            onChange={handleInputChange}
-                            placeholder="Enter MNE ID"
-                        />
-                    </Form.Group>
-                </Modal.Body>
-                <Modal.Footer>
-                    <Button variant="secondary" onClick={handleReset}>
-                        Cancel
-                    </Button>
-                    <Button variant="primary" type="submit">
-                        Add Device
-                    </Button>
-                </Modal.Footer>
-            </Form>
-        </Modal>
-    );
+          <div className="d-flex justify-content-end gap-2">
+            <Button variant="secondary" onClick={onHide}>
+              {t("device.add_device.buttons.cancel")}
+            </Button>
+            <Button disabled={loading} variant="primary" type="submit">
+              {loading ? (
+                <>
+                  <span className="spinner-border spinner-border-sm me-2" />
+                  {t("device.add_device.buttons.loading")}
+                </>
+              ) : (
+                t("device.add_device.buttons.submit")
+              )}
+            </Button>
+          </div>
+        </Form>
+      </Modal.Body>
+    </Modal>
+  );
 };
-
-export default AddDeviceModal;
\ No newline at end of file
+export default AddDeviceModal;
diff --git a/react-ui/src/components/devices/view_model/device.viewmodel.ts b/react-ui/src/components/devices/view_model/device.viewmodel.ts
index f2fd63553..5c4acc661 100755
--- a/react-ui/src/components/devices/view_model/device.viewmodel.ts
+++ b/react-ui/src/components/devices/view_model/device.viewmodel.ts
@@ -1,8 +1,20 @@
-import { useAppSelector } from '@hooks'
-import { useMemo } from 'react'
+import { useAppDispatch, useAppSelector } from '@hooks'
+import { useMemo, useState } from 'react'
+import { fetchPluginsThunk } from '../routines/plugin.routine'
 
 export const useDeviceViewModel = () => {
+    const [addModal, setAddModal] = useState<boolean>(false)
     const { selected: selectedDevice } = useAppSelector((state) => state.device)
+    const dispatch = useAppDispatch()
+
+    const openAddModal = () => {
+        dispatch(fetchPluginsThunk())
+        setAddModal(true)
+    }
+
+    const closeModal = () => {
+        setAddModal(false)
+    }
 
     const getYangModelJSON = (): JSON | null => {
         if (!selectedDevice?.json) {
@@ -23,6 +35,9 @@ export const useDeviceViewModel = () => {
 
     return {
         jsonYang,
-        selectedDevice
+        selectedDevice,
+        openAddModal,
+        closeModal,
+        addModal
     }
 }
diff --git a/react-ui/src/components/devices/view_model/modal.viewmodel.ts b/react-ui/src/components/devices/view_model/modal.viewmodel.ts
index de9bbf68e..98742bd34 100644
--- a/react-ui/src/components/devices/view_model/modal.viewmodel.ts
+++ b/react-ui/src/components/devices/view_model/modal.viewmodel.ts
@@ -1,10 +1,94 @@
-import { useEffect } from "react"
+import { NetworkelementAddListRequest, NetworkelementSetMne, useNetworkElementServiceAddListMutation } from "@api/api";
+import { useAppDispatch, useAppSelector } from "@hooks";
+import { fetchUser } from "@shared/routine/user.routine";
+import { useState } from "react";
+import { SubmitHandler, useForm } from "react-hook-form";
+import { useTranslation } from "react-i18next";
+import { toast } from "react-toastify";
 
+interface FormData {
+    address: string;
+    mneName: string;
+    pluginId: string;
+    transportOption: {
+        address: string;
+        username: string;
+        password: string;
+        tls: boolean;
+        gnmiTransportOption: Object;
+    };
+    gnmiSubscribePaths: string[];
+}
 
-export const useModalViewModel = () => {
+type ModalViewModelType = {
+    hide: () => void
+}
 
+export const useModalViewModel = ({ hide }: ModalViewModelType) => {
+    const dispatch = useAppDispatch()
+    const [addNetworkElement] = useNetworkElementServiceAddListMutation();
+    const [loading, setLoading] = useState<boolean>(false)
+    const { t } = useTranslation('common')
 
-    useEffect(() => {
+    const {
+        register,
+        handleSubmit,
+        setError,
+        clearErrors,
+        formState: { errors },
+        reset: resetModal
+    } = useForm<FormData>();
 
-    }, [])
+    const { user } = useAppSelector(state => state.user);
+
+    const reset = () => { resetModal(); hide(); }
+    const success = () => { toast.success(t('device.add_device.success')); reset(); dispatch(fetchUser()) }
+
+
+    const onSubmit: SubmitHandler<FormData> = async (data) => {
+        clearErrors()
+        setLoading(true)
+        const mne: NetworkelementSetMne = {
+            ...data,
+            gnmiSubscribePaths: [],
+            transportOption: {
+                ...data.transportOption,
+                gnmiTransportOption: {},
+            }
+        }
+
+        if (!user?.id) {
+            toast.error("global.error.missing_user")
+            return
+        }
+
+        const request: NetworkelementAddListRequest = {
+            timestamp: Date.now().toString(),
+            mne: [mne],
+            pid: user.id
+        };
+
+        try {
+            const response = await addNetworkElement({ networkelementAddListRequest: request });
+            setLoading(false)
+
+            if (response.error) {
+                const error = response.error as any
+                setError('root', error.data)
+                return
+            }
+
+            success()
+        } catch (error) {
+            setError('root', error?.data?.message || undefined)
+        }
+    }
+
+    return {
+        onSubmit,
+        handleSubmit: handleSubmit(onSubmit),
+        register,
+        errors,
+        loading
+    }
 }
\ No newline at end of file
diff --git a/react-ui/src/i18n/locales/en/translations.json b/react-ui/src/i18n/locales/en/translations.json
index 92fb59d85..8a81a03e9 100755
--- a/react-ui/src/i18n/locales/en/translations.json
+++ b/react-ui/src/i18n/locales/en/translations.json
@@ -14,6 +14,9 @@
             },
             "box": {
                 "lastUpdate": "Last updated {{seconds}} seconds ago"
+            },
+            "error": {
+                "missing_user": "Error: User information. Please relogin and try it again"
             }
         },
         "json_viewer": {
@@ -43,6 +46,49 @@
                     "title": "Configuration"
                 }
             },
+            "add_device": {
+                "success": "Device successfully added",
+                "title": "Add New Device",
+                "error": "An error occurred on save",
+                "fields": {
+                    "address": {
+                        "label": "IPv4 address",
+                        "placeholder": "172.100.0.1",
+                        "required": "Ipv4 Address is required"
+                    },
+                    "mne_name": {
+                        "label": "MNE Name",
+                        "placeholder": "Enter MNE name",
+                        "required": "MNE name is required"
+                    },
+                    "plugin": {
+                        "label": "Plugin",
+                        "placeholder": "Select plugin...",
+                        "required": "Plugin selection is required"
+                    },
+                    "tls": {
+                        "label": "TLS Enabled"
+                    },
+                    "credentials": {
+                        "title": "Credentials",
+                        "username": {
+                            "label": "Username",
+                            "placeholder": "Enter username",
+                            "required": "Username is required"
+                        },
+                        "password": {
+                            "label": "Password",
+                            "placeholder": "Enter password",
+                            "required": "Password is required"
+                        }
+                    }
+                },
+                "buttons": {
+                    "cancel": "Cancel",
+                    "submit": "Add Device",
+                    "loading": "Adding..."
+                }
+            },
             "table": {
                 "header": {
                     "name": "Name",
diff --git a/react-ui/src/shared/api/api.ts b/react-ui/src/shared/api/api.ts
index 32969f168..e0f35f0b7 100755
--- a/react-ui/src/shared/api/api.ts
+++ b/react-ui/src/shared/api/api.ts
@@ -4,6 +4,7 @@ export const addTagTypes = [
     'ConfigurationManagementService',
     'AuthService',
     'NetworkElementService',
+    'PluginInternalService',
     'PndService',
     'RoleService',
     'RoutingTableService',
@@ -214,6 +215,18 @@ const injectedRtkApi = api
                 }),
                 invalidatesTags: ['NetworkElementService'],
             }),
+            pluginInternalServiceGetAvailablePlugins: build.query<
+                PluginInternalServiceGetAvailablePluginsApiResponse,
+                PluginInternalServiceGetAvailablePluginsApiArg
+            >({
+                query: (queryArg) => ({
+                    url: `/plugins`,
+                    params: {
+                        timestamp: queryArg.timestamp,
+                    },
+                }),
+                providesTags: ['PluginInternalService'],
+            }),
             pndServiceGetPnd: build.query<
                 PndServiceGetPndApiResponse,
                 PndServiceGetPndApiArg
@@ -680,6 +693,11 @@ export type NetworkElementServiceUpdateApiResponse =
 export type NetworkElementServiceUpdateApiArg = {
     networkelementUpdateNetworkElementRequest: TodoChangeNameToFitTheRest
 }
+export type PluginInternalServiceGetAvailablePluginsApiResponse =
+    /** status 200 A successful response. */ GosdnpluginRegistryGetResponse
+export type PluginInternalServiceGetAvailablePluginsApiArg = {
+    timestamp?: string
+}
 export type PndServiceGetPndApiResponse =
     /** status 200 A successful response. */ PndGetPndResponse
 export type PndServiceGetPndApiArg = {
@@ -1183,6 +1201,11 @@ export type TodoChangeNameToFitTheRest = {
     timestamp?: string
     networkElement?: NetworkelementManagedNetworkElement
 }
+export type GosdnpluginRegistryGetResponse = {
+    /** Timestamp in nanoseconds since Epoch. */
+    timestamp?: string
+    plugins?: PluginRegistryPlugin[]
+}
 export type PndGetPndResponse = {
     /** Timestamp in nanoseconds since Epoch. */
     timestamp?: string
@@ -1432,6 +1455,7 @@ export const {
     useNetworkElementServiceGetIntendedPathQuery,
     useNetworkElementServiceGetPathQuery,
     useNetworkElementServiceUpdateMutation,
+    usePluginInternalServiceGetAvailablePluginsQuery,
     usePndServiceGetPndQuery,
     usePndServiceGetPndListQuery,
     usePndServiceCreatePndListMutation,
diff --git a/react-ui/src/stores/persist.store.ts b/react-ui/src/stores/persist.store.ts
index e12467ed9..91d961cad 100755
--- a/react-ui/src/stores/persist.store.ts
+++ b/react-ui/src/stores/persist.store.ts
@@ -1,4 +1,5 @@
 import deviceReducer from '@component/devices/reducer/device.reducer'
+import pluginReducer from '@component/devices/reducer/plugin.reducer'
 import jsonViewerReducer from '@shared/components/json_viewer/reducer/json_viewer.reducer'
 import routineReducer from '@shared/reducer/routine.reducer'
 import userReducer from '@shared/reducer/user.reducer'
@@ -7,6 +8,8 @@ import { persistReducer } from 'redux-persist'
 import storage from 'redux-persist/es/storage'
 import { emptySplitApi } from './api.store'
 
+
+
 /** local storage config */
 const rootPersistConfig = {
     key: 'root',
@@ -19,6 +22,7 @@ const rootReducer = combineReducers({
     device: deviceReducer,
     routine: routineReducer,
     json_viwer: jsonViewerReducer,
+    plugin: pluginReducer,
     [emptySplitApi.reducerPath]: emptySplitApi.reducer,
 })
 
diff --git a/react-ui/yarn.lock b/react-ui/yarn.lock
index 224cc0ddd..5e4047ff1 100755
--- a/react-ui/yarn.lock
+++ b/react-ui/yarn.lock
@@ -8887,6 +8887,11 @@ react-grid-layout@^1.5.0:
     react-resizable "^3.0.5"
     resize-observer-polyfill "^1.5.1"
 
+react-hook-form@^7.54.2:
+  version "7.54.2"
+  resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.54.2.tgz#8c26ed54c71628dff57ccd3c074b1dd377cfb211"
+  integrity sha512-eHpAUgUjWbZocoQYUHposymRb4ZP6d0uwUnooL2uOybA9/3tPUvoAKqEWK1WaSiTxxOfTpffNZP7QwlnM3/gEg==
+
 react-i18next@^15.0.0:
   version "15.1.4"
   resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-15.1.4.tgz#65c03c31a5e42202000652e163f22f23a9306a60"
-- 
GitLab


From 72bb539eecb84bb84a9f6bef691dff36b60a4fc7 Mon Sep 17 00:00:00 2001
From: Matthias Feyll <matthias.feyll@stud.h-da.de>
Date: Fri, 7 Feb 2025 11:11:26 +0100
Subject: [PATCH 79/79] remove trailing whitespace

---
 controller/northbound/server/plugin.go | 1 -
 1 file changed, 1 deletion(-)

diff --git a/controller/northbound/server/plugin.go b/controller/northbound/server/plugin.go
index 8e73994d3..25f4b3cff 100755
--- a/controller/northbound/server/plugin.go
+++ b/controller/northbound/server/plugin.go
@@ -68,7 +68,6 @@ func (pis *PluginInternalServer) GetAvailablePlugins(ctx context.Context, reques
 	}
 
 	return pis.pluginRegistryClient.GetAll(ctx, getAllRequest)
-
 }
 
 func (pis *PluginInternalServer) GetPluginSchema(request *pipb.GetPluginSchemaRequest, stream pipb.PluginInternalService_GetPluginSchemaServer) error {
-- 
GitLab