diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 446770e257ed78594cf83d97ffc60bf10e86dad4..b69a30ca26094514dd299e1e0b99d69a965efa24 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -4,6 +4,8 @@ variables:
     GOSDN_INTEGRATION_TEST_IMAGE: "${CI_REGISTRY_IMAGE}/integration-tests:${CI_COMMIT_SHA}"
     CEOS_IMAGE: "${CI_PCONTAINERS_REGISTRY_IMAGE}/ceos:4.28.2F"
     GOLANG_VERSION: "1.23"
+    NODE_VERSION: "23"
+    NGINX_VERSION: "1.27"
     GNMI_TARGET_IMAGE: registry.code.fbi.h-da.de/danet/gnmi-target/debian:master
     GNMI_TARGET_INTEGRATION_IMAGE: "$CI_REGISTRY_IMAGE/gnmi-target-integration-test:${CI_COMMIT_SHA}"
     DOCKER_TLS_CERTDIR: "/certs"
diff --git a/.gitlab/ci/.build-binaries.yml b/.gitlab/ci/.build-binaries.yml
index 174203fdcd52622712b38ef0718612d6cf873a94..4877cd1697d13de412485f281f2bf2b46a8b1019 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 da70dcba2d6ae122b967c2417c014750cbed26b0..4b62da4e255aba18fe2da9ed278289b5a44c90bb 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" --build-arg "NODE_VERSION=$NODE_VERSION" --build-arg "NGINX_VERSION=$NGINX_VERSION" --build-arg "GITLAB_PROXY=${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/" .
+        - 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/.code-quality-ci.yml b/.gitlab/ci/.code-quality-ci.yml
index d054508c42f8f2a9bca5020a40c09aebd06516d5..95ed3abe96e1220d751c05e5e16224a29e47b99d 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.4-alpine
     stage: analyze
     script:
         # writes golangci-lint output to gl-code-quality-report.json
diff --git a/.gitlab/ci/.react-ui.yml b/.gitlab/ci/.react-ui.yml
deleted file mode 100644
index 873b694c892b39870eb60ad629f836055089734b..0000000000000000000000000000000000000000
--- 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/.gitlab/ci/.renovate.yml b/.gitlab/ci/.renovate.yml
index 55c8ea3356625716b25ede02abb096628ee318cf..b8ccc7b58042eabb4384fcbb7a0bfdeda7eddb4b 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.161.4
 
     variables:
         LOG_LEVEL: debug
diff --git a/.golangci.yml b/.golangci.yml
index cdd404e55c3ed172a14d18e70ece0ec4be7ebe53..42bb6ac6b31f1abf94ecc1e47bcf910873a99dc3 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 888644abed5135d8bf2364302499eefd2f2ea0e4..693329772ec396aada21e43a6586306b8949af60 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
@@ -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/README.md b/README.md
index e8e273c2edceb61f62cffc6e994ee54d33e67b56..a418a5ab7f16d48e502888519991e8f9476f7c03 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.
diff --git a/controller/cmd/root.go b/controller/cmd/root.go
index c2dd7fb6c2ff15238c3a6a630fa1d532d31867dc..4b52eb4a4bcf8c2068e662f42524eea42b5113e0 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/northbound/server/auth_test.go b/controller/northbound/server/auth_test.go
index e5c9e7389d443c0f653f53a3c5f32966f5c2671d..956ef2be19b5da9be5eebe2636763bb7c91fe7b5 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 bb787a4160530b0454d4b2c0198f47c0f9a98ffc..2d75e067843f15c594d6d34e2b0a503d058c8582 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 44ce77b57b19c31d5cc6292e5af5c2ac265e3a42..dea560a452ff02ff710d6ca71fcc251d8f57472d 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 4a1c663279ce5607a40ff3dd1fd8d87f03d7e0bf..9fcdf4d610cb5685e69e231bd2d65cde95a7e9e8 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 7a4636caabf0f8d66d6e36383e59026d2f376315..dd95d8f2e8c56ba51bf01ade6d6cf5efa0831758 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/controller/nucleus/networkElementWatcher.go b/controller/nucleus/networkElementWatcher.go
index 8b542d086ca5c61e7fb5d776137c6c11260fd858..07ad775f253c361a7921c6699d95b2681c1e7002 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 {
diff --git a/controller/store/utils.go b/controller/store/utils.go
index 9d8ebc838e88f88fedd863f15d26ad04b979c9a3..d29dcf421fdbd25375fa50133b5dbf0e3cb09a45 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
 		}
diff --git a/dev_env_data/clab/gosdn_slim.clab.yaml b/dev_env_data/clab/gosdn_slim.clab.yaml
index f4d76846cddf22b054f8cee3c4e39d70589cb7ea..b3ef8eb088890c2e63d349c11d4d7de5f60a5e65 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 4e7664161a7a65487281e203f52d866271815d7c..2544e7b0f3728d57d64b3138dd7f5d6f74f7f4cc 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/go.mod b/go.mod
index 2879fe71145322dbb2465f3d4479af08aec81257..75b8c20106afb07862cb813b8fba2da6cb60ce09 100644
--- a/go.mod
+++ b/go.mod
@@ -1,16 +1,18 @@
 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-20241115153057-bd75d7f26a44
+	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
 	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.26.0
 	github.com/mitchellh/go-homedir v1.1.0
-	github.com/openconfig/gnmi v0.11.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
@@ -18,14 +20,14 @@ 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
-	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/protobuf v1.35.2
+	go.mongodb.org/mongo-driver/v2 v2.0.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
 )
 
@@ -41,13 +43,13 @@ 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
 	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 +66,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
@@ -77,37 +79,38 @@ 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/sys v0.28.0 // indirect
-	golang.org/x/term v0.27.0 // indirect
+	golang.org/x/crypto v0.32.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
 	gopkg.in/ini.v1 v1.67.0 // indirect
 )
 
 require (
-	buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20241127180247-a33202765966.1
-	github.com/bufbuild/protovalidate-go v0.7.3
+	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
-	github.com/lesismal/nbio v1.5.12
-	google.golang.org/genproto/googleapis/api v0.0.0-20241202173237-19429a94021a
+	github.com/lesismal/nbio v1.6.2
+	go.mongodb.org/mongo-driver v1.17.2
+	google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489
 )
 
 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
 	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
-	github.com/lesismal/llib v1.1.13 // 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
@@ -122,7 +125,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
-	google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 // indirect
+	golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // 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 880acc9d162c50002ebb01111d0ee6477af85d60..6c670172e812281bbd97d85d22a2ff8a3fb36d4d 100644
--- a/go.sum
+++ b/go.sum
@@ -16,8 +16,18 @@ 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=
+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=
+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=
+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=
@@ -56,6 +66,10 @@ 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/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=
@@ -71,6 +85,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=
@@ -124,6 +140,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=
@@ -146,6 +164,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=
@@ -169,6 +189,10 @@ 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/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=
@@ -190,6 +214,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=
@@ -206,12 +232,22 @@ 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/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=
 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/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=
@@ -262,6 +298,10 @@ 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/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=
@@ -296,6 +336,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=
@@ -342,6 +384,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=
@@ -390,6 +434,9 @@ 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.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=
@@ -411,9 +458,15 @@ 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/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=
+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=
@@ -446,6 +499,10 @@ 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/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=
@@ -463,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=
@@ -501,6 +560,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=
@@ -514,6 +575,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=
@@ -575,6 +638,18 @@ 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/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/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/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=
@@ -595,6 +670,16 @@ 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/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/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=
@@ -613,6 +698,12 @@ 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 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=
@@ -633,6 +724,14 @@ 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=
+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=
+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=
diff --git a/makefiles/container/Makefile b/makefiles/container/Makefile
index c9c21b9728af4606335ea425a187a55dd09f5ad1..6e3b97242bdd968d9e4236440721c9bea30bc805 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 05d3aad83fd593051616bfc5345367d961f8adeb..292a134fd5707a0508ad136b8a01d8e2f3d0890d 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 0000000000000000000000000000000000000000..5ecec04724f8685ae46c6f5ddf66a4c92844754f
--- /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 f4644ee1036b55d30673e0290d3a89aec8a68c60..3fe6616602bc7d3a110504acadb6c47669777a9a 100644
--- a/react-ui/docker/webserver/Dockerfile
+++ b/react-ui/docker/webserver/Dockerfile
@@ -1,4 +1,16 @@
-FROM nginx:alpine3.20
+ARG NODE_VERSION=23
+ARG NGINX_VERSION=1.27
+ARG GITLAB_PROXY
 
-COPY dist /usr/share/nginx/html
-COPY docker/webserver/nginx.conf /etc/nginx/nginx.conf 
\ No newline at end of file
+FROM ${GITLAB_PROXY}node:$NODE_VERSION-alpine 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
+
+# webserver
+FROM ${GITLAB_PROXY}nginx:$NGINX_VERSION-alpine
+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
diff --git a/react-ui/docker/webserver/nginx.conf b/react-ui/docker/webserver/nginx.conf
index 87066f6ab89b1a840816f93fedc989e0d0736bfb..eb4fc2be925602e892b2bdb0a134d5016cc2c736 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 ad0f0cd0b20382110f1dbff59206f95c1d5a14f2..fb6cb2a21737c17e269f4dbc7fd1b2befdd5e6ae 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 fefafe05a692ebf39a8879ac440fcff0f549ec60..fc4ce4a01c9588f72d40aee0e7aeb16d002e068e 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/, ''),