diff --git a/package-lock.json b/package-lock.json
index 45c6287f8725e19e617dfef4de6a9ef61b8d5d8c..be37a3e534aed19236f7bfe8186a5a27bf938ed0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,7 +14,7 @@
         "@aws-sdk/s3-request-presigner": "<3.530.0",
         "@fortawesome/fontawesome-free": "~6.5.0",
         "@popperjs/core": "~2.11.8",
-        "ajv": "~8.14.0",
+        "ajv": "~8.16.0",
         "bootstrap": "~5.3.0",
         "chart.js": "~4.4.0",
         "chartjs-plugin-zoom": "~2.0.1",
@@ -52,7 +52,7 @@
         "highlight.js": "^11.9.0",
         "npm-run-all": "~4.1.5",
         "openapi-typescript-codegen": "^0.29.0",
-        "prettier": "~3.2.0",
+        "prettier": "~3.3.0",
         "rollup-plugin-node-polyfills": "~0.2.1",
         "sass": "^1.66.0",
         "typescript": "~5.4.0",
@@ -61,9 +61,9 @@
       }
     },
     "node_modules/@apidevtools/json-schema-ref-parser": {
-      "version": "11.6.2",
-      "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.6.2.tgz",
-      "integrity": "sha512-ENUdLLT04aDbbHCRwfKf8gR67AhV0CdFrOAtk+FcakBAgaq6ds3HLK9X0BCyiFUz8pK9uP+k6YZyJaGG7Mt7vQ==",
+      "version": "11.6.4",
+      "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.6.4.tgz",
+      "integrity": "sha512-9K6xOqeevacvweLGik6LnZCb1fBtCOSIWQs8d096XGeqoLKC33UVMGz9+77Gw44KvbH4pKcQPWo4ZpxkXYj05w==",
       "dev": true,
       "dependencies": {
         "@jsdevtools/ono": "^7.1.3",
@@ -929,9 +929,9 @@
       }
     },
     "node_modules/@babel/parser": {
-      "version": "7.24.6",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.6.tgz",
-      "integrity": "sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==",
+      "version": "7.24.7",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz",
+      "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==",
       "bin": {
         "parser": "bin/babel-parser.js"
       },
@@ -1368,9 +1368,9 @@
       }
     },
     "node_modules/@eslint-community/regexpp": {
-      "version": "4.10.0",
-      "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
-      "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
+      "version": "4.10.1",
+      "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz",
+      "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==",
       "dev": true,
       "engines": {
         "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
@@ -2476,9 +2476,9 @@
       "dev": true
     },
     "node_modules/@types/node": {
-      "version": "20.12.12",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz",
-      "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==",
+      "version": "20.14.2",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz",
+      "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==",
       "dev": true,
       "dependencies": {
         "undici-types": "~5.26.4"
@@ -2509,16 +2509,16 @@
       "dev": true
     },
     "node_modules/@typescript-eslint/eslint-plugin": {
-      "version": "7.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.11.0.tgz",
-      "integrity": "sha512-P+qEahbgeHW4JQ/87FuItjBj8O3MYv5gELDzr8QaQ7fsll1gSMTYb6j87MYyxwf3DtD7uGFB9ShwgmCJB5KmaQ==",
+      "version": "7.12.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.12.0.tgz",
+      "integrity": "sha512-7F91fcbuDf/d3S8o21+r3ZncGIke/+eWk0EpO21LXhDfLahriZF9CGj4fbAetEjlaBdjdSm9a6VeXbpbT6Z40Q==",
       "dev": true,
       "dependencies": {
         "@eslint-community/regexpp": "^4.10.0",
-        "@typescript-eslint/scope-manager": "7.11.0",
-        "@typescript-eslint/type-utils": "7.11.0",
-        "@typescript-eslint/utils": "7.11.0",
-        "@typescript-eslint/visitor-keys": "7.11.0",
+        "@typescript-eslint/scope-manager": "7.12.0",
+        "@typescript-eslint/type-utils": "7.12.0",
+        "@typescript-eslint/utils": "7.12.0",
+        "@typescript-eslint/visitor-keys": "7.12.0",
         "graphemer": "^1.4.0",
         "ignore": "^5.3.1",
         "natural-compare": "^1.4.0",
@@ -2542,15 +2542,15 @@
       }
     },
     "node_modules/@typescript-eslint/parser": {
-      "version": "7.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.11.0.tgz",
-      "integrity": "sha512-yimw99teuaXVWsBcPO1Ais02kwJ1jmNA1KxE7ng0aT7ndr1pT1wqj0OJnsYVGKKlc4QJai86l/025L6z8CljOg==",
+      "version": "7.12.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.12.0.tgz",
+      "integrity": "sha512-dm/J2UDY3oV3TKius2OUZIFHsomQmpHtsV0FTh1WO8EKgHLQ1QCADUqscPgTpU+ih1e21FQSRjXckHn3txn6kQ==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/scope-manager": "7.11.0",
-        "@typescript-eslint/types": "7.11.0",
-        "@typescript-eslint/typescript-estree": "7.11.0",
-        "@typescript-eslint/visitor-keys": "7.11.0",
+        "@typescript-eslint/scope-manager": "7.12.0",
+        "@typescript-eslint/types": "7.12.0",
+        "@typescript-eslint/typescript-estree": "7.12.0",
+        "@typescript-eslint/visitor-keys": "7.12.0",
         "debug": "^4.3.4"
       },
       "engines": {
@@ -2570,13 +2570,13 @@
       }
     },
     "node_modules/@typescript-eslint/scope-manager": {
-      "version": "7.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.11.0.tgz",
-      "integrity": "sha512-27tGdVEiutD4POirLZX4YzT180vevUURJl4wJGmm6TrQoiYwuxTIY98PBp6L2oN+JQxzE0URvYlzJaBHIekXAw==",
+      "version": "7.12.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.12.0.tgz",
+      "integrity": "sha512-itF1pTnN6F3unPak+kutH9raIkL3lhH1YRPGgt7QQOh43DQKVJXmWkpb+vpc/TiDHs6RSd9CTbDsc/Y+Ygq7kg==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "7.11.0",
-        "@typescript-eslint/visitor-keys": "7.11.0"
+        "@typescript-eslint/types": "7.12.0",
+        "@typescript-eslint/visitor-keys": "7.12.0"
       },
       "engines": {
         "node": "^18.18.0 || >=20.0.0"
@@ -2587,13 +2587,13 @@
       }
     },
     "node_modules/@typescript-eslint/type-utils": {
-      "version": "7.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.11.0.tgz",
-      "integrity": "sha512-WmppUEgYy+y1NTseNMJ6mCFxt03/7jTOy08bcg7bxJJdsM4nuhnchyBbE8vryveaJUf62noH7LodPSo5Z0WUCg==",
+      "version": "7.12.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.12.0.tgz",
+      "integrity": "sha512-lib96tyRtMhLxwauDWUp/uW3FMhLA6D0rJ8T7HmH7x23Gk1Gwwu8UZ94NMXBvOELn6flSPiBrCKlehkiXyaqwA==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/typescript-estree": "7.11.0",
-        "@typescript-eslint/utils": "7.11.0",
+        "@typescript-eslint/typescript-estree": "7.12.0",
+        "@typescript-eslint/utils": "7.12.0",
         "debug": "^4.3.4",
         "ts-api-utils": "^1.3.0"
       },
@@ -2614,9 +2614,9 @@
       }
     },
     "node_modules/@typescript-eslint/types": {
-      "version": "7.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.11.0.tgz",
-      "integrity": "sha512-MPEsDRZTyCiXkD4vd3zywDCifi7tatc4K37KqTprCvaXptP7Xlpdw0NR2hRJTetG5TxbWDB79Ys4kLmHliEo/w==",
+      "version": "7.12.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.12.0.tgz",
+      "integrity": "sha512-o+0Te6eWp2ppKY3mLCU+YA9pVJxhUJE15FV7kxuD9jgwIAa+w/ycGJBMrYDTpVGUM/tgpa9SeMOugSabWFq7bg==",
       "dev": true,
       "engines": {
         "node": "^18.18.0 || >=20.0.0"
@@ -2627,13 +2627,13 @@
       }
     },
     "node_modules/@typescript-eslint/typescript-estree": {
-      "version": "7.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.11.0.tgz",
-      "integrity": "sha512-cxkhZ2C/iyi3/6U9EPc5y+a6csqHItndvN/CzbNXTNrsC3/ASoYQZEt9uMaEp+xFNjasqQyszp5TumAVKKvJeQ==",
+      "version": "7.12.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.12.0.tgz",
+      "integrity": "sha512-5bwqLsWBULv1h6pn7cMW5dXX/Y2amRqLaKqsASVwbBHMZSnHqE/HN4vT4fE0aFsiwxYvr98kqOWh1a8ZKXalCQ==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "7.11.0",
-        "@typescript-eslint/visitor-keys": "7.11.0",
+        "@typescript-eslint/types": "7.12.0",
+        "@typescript-eslint/visitor-keys": "7.12.0",
         "debug": "^4.3.4",
         "globby": "^11.1.0",
         "is-glob": "^4.0.3",
@@ -2655,15 +2655,15 @@
       }
     },
     "node_modules/@typescript-eslint/utils": {
-      "version": "7.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.11.0.tgz",
-      "integrity": "sha512-xlAWwPleNRHwF37AhrZurOxA1wyXowW4PqVXZVUNCLjB48CqdPJoJWkrpH2nij9Q3Lb7rtWindtoXwxjxlKKCA==",
+      "version": "7.12.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.12.0.tgz",
+      "integrity": "sha512-Y6hhwxwDx41HNpjuYswYp6gDbkiZ8Hin9Bf5aJQn1bpTs3afYY4GX+MPYxma8jtoIV2GRwTM/UJm/2uGCVv+DQ==",
       "dev": true,
       "dependencies": {
         "@eslint-community/eslint-utils": "^4.4.0",
-        "@typescript-eslint/scope-manager": "7.11.0",
-        "@typescript-eslint/types": "7.11.0",
-        "@typescript-eslint/typescript-estree": "7.11.0"
+        "@typescript-eslint/scope-manager": "7.12.0",
+        "@typescript-eslint/types": "7.12.0",
+        "@typescript-eslint/typescript-estree": "7.12.0"
       },
       "engines": {
         "node": "^18.18.0 || >=20.0.0"
@@ -2677,12 +2677,12 @@
       }
     },
     "node_modules/@typescript-eslint/visitor-keys": {
-      "version": "7.11.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.11.0.tgz",
-      "integrity": "sha512-7syYk4MzjxTEk0g/w3iqtgxnFQspDJfn6QKD36xMuuhTzjcxY7F8EmBLnALjVyaOF1/bVocu3bS/2/F7rXrveQ==",
+      "version": "7.12.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.12.0.tgz",
+      "integrity": "sha512-uZk7DevrQLL3vSnfFl5bj4sL75qC9D6EdjemIdbtkuUmIheWpuiiylSY01JxJE7+zGrOWDZrp1WxOuDntvKrHQ==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "7.11.0",
+        "@typescript-eslint/types": "7.12.0",
         "eslint-visitor-keys": "^3.4.3"
       },
       "engines": {
@@ -2700,9 +2700,9 @@
       "dev": true
     },
     "node_modules/@vitejs/plugin-vue": {
-      "version": "5.0.4",
-      "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz",
-      "integrity": "sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==",
+      "version": "5.0.5",
+      "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.5.tgz",
+      "integrity": "sha512-LOjm7XeIimLBZyzinBQ6OSm3UBCNVCpLkxGC0oWmm2YPzVZoxMsdvNVimLTBzpAnR9hl/yn1SHGuRfe6/Td9rQ==",
       "dev": true,
       "engines": {
         "node": "^18.0.0 || >=20.0.0"
@@ -2805,9 +2805,9 @@
       }
     },
     "node_modules/@vue/devtools-api": {
-      "version": "6.6.1",
-      "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.1.tgz",
-      "integrity": "sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA=="
+      "version": "6.6.3",
+      "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.3.tgz",
+      "integrity": "sha512-0MiMsFma/HqA6g3KLKn+AGpL1kgKhFWszC9U29NfpWK5LE7bjeXxySWJrOJ77hBz+TBrBQ7o4QJqbPbqbs8rJw=="
     },
     "node_modules/@vue/eslint-config-prettier": {
       "version": "9.0.0",
@@ -2942,9 +2942,9 @@
       }
     },
     "node_modules/ajv": {
-      "version": "8.14.0",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.14.0.tgz",
-      "integrity": "sha512-oYs1UUtO97ZO2lJ4bwnWeQW8/zvOIQLGKcvPTsWmvc2SYgBb+upuNS5NxoLaMU4h8Ju3Nbj6Cq8mD2LQoqVKFA==",
+      "version": "8.16.0",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz",
+      "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==",
       "dependencies": {
         "fast-deep-equal": "^3.1.3",
         "json-schema-traverse": "^1.0.0",
@@ -3433,9 +3433,9 @@
       "dev": true
     },
     "node_modules/debug": {
-      "version": "4.3.4",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "version": "4.3.5",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
+      "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
       "dev": true,
       "dependencies": {
         "ms": "2.1.2"
@@ -3523,9 +3523,9 @@
       }
     },
     "node_modules/dompurify": {
-      "version": "3.1.4",
-      "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.4.tgz",
-      "integrity": "sha512-2gnshi6OshmuKil8rMZuQCGiUF3cUxHY3NGDzUAdUx/NPEe5DVnO8BDoAQouvgwnx0R/+a6jUn36Z0FSdq8vww=="
+      "version": "3.1.5",
+      "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.5.tgz",
+      "integrity": "sha512-lwG+n5h8QNpxtyrJW/gJWckL+1/DQiYMX8f7t8Z2AZTPw1esVrqjI63i7Zc2Gz0aKzLVMYC1V1PL/ky+aY/NgA=="
     },
     "node_modules/entities": {
       "version": "4.5.0",
@@ -5639,9 +5639,9 @@
       }
     },
     "node_modules/pinia/node_modules/vue-demi": {
-      "version": "0.14.7",
-      "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz",
-      "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==",
+      "version": "0.14.8",
+      "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.8.tgz",
+      "integrity": "sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==",
       "hasInstallScript": true,
       "bin": {
         "vue-demi-fix": "bin/vue-demi-fix.js",
@@ -5722,9 +5722,9 @@
       }
     },
     "node_modules/prettier": {
-      "version": "3.2.5",
-      "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz",
-      "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==",
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.1.tgz",
+      "integrity": "sha512-7CAwy5dRsxs8PHXT3twixW9/OEll8MLE0VRPCJyl7CkS6VHGPSlsVaWTiASPTyGyYRyApxlaWTzwUxVNrhcwDg==",
       "dev": true,
       "bin": {
         "prettier": "bin/prettier.cjs"
@@ -6054,9 +6054,9 @@
       }
     },
     "node_modules/sass": {
-      "version": "1.77.2",
-      "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.2.tgz",
-      "integrity": "sha512-eb4GZt1C3avsX3heBNlrc7I09nyT00IUuo4eFhAbeXWU2fvA7oXI53SxODVAA+zgZCk9aunAZgO+losjR3fAwA==",
+      "version": "1.77.4",
+      "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.4.tgz",
+      "integrity": "sha512-vcF3Ckow6g939GMA4PeU7b2K/9FALXk2KF9J87txdHzXbUF9XRQRwSxcAs/fGaTnJeBFd7UoV22j3lzMLdM0Pw==",
       "dev": true,
       "dependencies": {
         "chokidar": ">=3.0.0 <4.0.0",
@@ -6447,9 +6447,9 @@
       }
     },
     "node_modules/tslib": {
-      "version": "2.6.2",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
-      "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+      "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ=="
     },
     "node_modules/type-check": {
       "version": "0.4.0",
@@ -6640,9 +6640,9 @@
       }
     },
     "node_modules/vite": {
-      "version": "5.2.11",
-      "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.11.tgz",
-      "integrity": "sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==",
+      "version": "5.2.13",
+      "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.13.tgz",
+      "integrity": "sha512-SSq1noJfY9pR3I1TUENL3rQYDQCFqgD+lM6fTRAM8Nv6Lsg5hDLaXkjETVeBt+7vZBCMoibD+6IWnT2mJ+Zb/A==",
       "dev": true,
       "dependencies": {
         "esbuild": "^0.20.1",
@@ -7121,9 +7121,9 @@
       }
     },
     "node_modules/vue-eslint-parser": {
-      "version": "9.4.2",
-      "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.2.tgz",
-      "integrity": "sha512-Ry9oiGmCAK91HrKMtCrKFWmSFWvYkpGglCeFAIqDdr9zdXmMMpJOmUJS7WWsW7fX81h6mwHmUZCQQ1E0PkSwYQ==",
+      "version": "9.4.3",
+      "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz",
+      "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==",
       "dev": true,
       "dependencies": {
         "debug": "^4.3.4",
diff --git a/package.json b/package.json
index 142ddef1ccc6fa6f09741e4161fc2fa9c6a973a6..fece0f765c7be49bec6b7c3abae08de28887b33c 100644
--- a/package.json
+++ b/package.json
@@ -18,7 +18,7 @@
     "@aws-sdk/s3-request-presigner": "<3.530.0",
     "@fortawesome/fontawesome-free": "~6.5.0",
     "@popperjs/core": "~2.11.8",
-    "ajv": "~8.14.0",
+    "ajv": "~8.16.0",
     "bootstrap": "~5.3.0",
     "chart.js": "~4.4.0",
     "chartjs-plugin-zoom": "~2.0.1",
@@ -56,7 +56,7 @@
     "highlight.js": "^11.9.0",
     "npm-run-all": "~4.1.5",
     "openapi-typescript-codegen": "^0.29.0",
-    "prettier": "~3.2.0",
+    "prettier": "~3.3.0",
     "rollup-plugin-node-polyfills": "~0.2.1",
     "sass": "^1.66.0",
     "typescript": "~5.4.0",
diff --git a/src/App.vue b/src/App.vue
index 190e60f004f0fb2b041d6f2e3e47e93ae22c441e..a3bef75cae380982e55d1128d9755588f159e95d 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -76,19 +76,19 @@ onBeforeMount(() => {
       to.meta.requiresDeveloperRole &&
       !(userRepository.workflowDev || userRepository.admin)
     ) {
-      return { name: "dashboard" };
+      return { name: "workflows" };
     } else if (
       to.meta.requiresReviewerRole &&
       !(userRepository.rewiewer || userRepository.admin)
     ) {
-      return { name: "dashboard" };
+      return "/";
     } else if (
       to.meta.requiresMaintainerRole &&
       !(userRepository.resourceMaintainer || userRepository.admin)
     ) {
-      return { name: "dashboard" };
+      return { name: "resources" };
     } else if (to.meta.adminRole && !userRepository.admin) {
-      return { name: "dashboard" };
+      return "/";
     } else if (to.name !== "login" && to.query.next) {
       // return to original path after login
       return { path: decodeURI(to.query.next as string) };
diff --git a/src/components/workflows/modals/ArbitraryWorkflowModal.vue b/src/components/workflows/modals/ArbitraryWorkflowModal.vue
index 6cf0681d247976f3ae80547e0edff2ed53a17899..132dd4a27f224721d79fb8aeaa6d96e7b0a60029 100644
--- a/src/components/workflows/modals/ArbitraryWorkflowModal.vue
+++ b/src/components/workflows/modals/ArbitraryWorkflowModal.vue
@@ -11,6 +11,10 @@ import {
 import { Collapse, Modal } from "bootstrap";
 import { useWorkflowStore } from "@/stores/workflows";
 import type { WorkflowModeOut } from "@/client";
+import { environment } from "@/environment";
+import { useS3KeyStore } from "@/stores/s3keys";
+import { useResourceStore } from "@/stores/resources";
+import { createDownloadUrl } from "@/utils/DownloadJson";
 
 const props = defineProps<{
   modalId: string;
@@ -25,6 +29,8 @@ const workflowRepositoryElement = ref<HTMLInputElement | undefined>(undefined);
 
 const router = useRouter();
 const workflowStore = useWorkflowStore();
+const s3KeyStore = useS3KeyStore();
+const resourceStore = useResourceStore();
 
 const workflow = reactive<{
   repository_url: string;
@@ -55,6 +61,14 @@ const workflowMode = reactive<{
   modeEnabled: false,
 });
 
+const executionEnvironmentState = reactive<{
+  cli: boolean;
+  cluster: boolean;
+}>({
+  cli: false,
+  cluster: false,
+});
+
 const formState = reactive<{
   loading: boolean;
   checkRepoLoading: boolean;
@@ -122,8 +136,199 @@ function viewWorkflow() {
     });
 }
 
+const resourcePathPrefix = computed<string>(() => {
+  let resourcePath: string | null = null;
+  for (const resource of resourceStore.resources) {
+    for (const version of resource.versions) {
+      if (version.cluster_path.length > 0) {
+        resourcePath = version.cluster_path;
+      }
+    }
+  }
+  if (resourcePath == null) {
+    return "";
+  }
+  const ind = resourcePath.search(/CLDB-[\da-f]{32}/);
+  if (ind == -1) {
+    return "";
+  }
+  return resourcePath.slice(0, ind - 1);
+});
+
+const nextflowConfig = computed<string>(() => {
+  if (executionEnvironmentState.cluster) {
+    return `// Nextflow config to emulate CloWM native execution
+aws {
+    accessKey = '${s3KeyStore.keys[0]?.access_key ?? ""}'
+    secretKey = '${s3KeyStore.keys[0]?.secret_key ?? ""}'
+    client {
+       endpoint = '${environment.S3_URL}'
+       s3PathStyleAccess = true
+    }
+}
+
+// Docker container options
+docker {
+    enabled = true
+    runOptions = "-u \\$(id -u):\\$(id -g) -q \\
+                  -v ${resourcePathPrefix.value}:${resourcePathPrefix.value}:ro \\
+                  -v /var/lib/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw \\
+                  -v /var/lib/lxcfs/proc/diskstats:/proc/diskstats:rw \\
+                  -v /var/lib/lxcfs/proc/meminfo:/proc/meminfo:rw  \\
+                  -v /var/lib/lxcfs/proc/stat:/proc/stat:rw \\
+                  -v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw \\
+                  -v /var/lib/lxcfs/proc/uptime:/proc/uptime:rw"  
+}
+
+// Disable unwanted features
+// Attention: Docker is the only supported container engine so far!
+weblog.enabled = false
+shifter.enabled = false
+singularity.enabled = false
+podman.enabled = false
+charliecloud.enabled = false
+dag.enabled = false
+trace.enabled = false
+
+// Nextflow provenance tracking plugin
+plugins {
+  id 'nf-prov'
+}
+
+prov {
+  enabled = true
+  formats {
+    legacy {
+      file = "./nf-prov_manifest.json"
+      overwrite = true
+    }
+    bco {
+      file = "./nf-prov_bco.json"
+      overwrite = true
+    }
+    dag {
+      file = "./nf-prov_dag.html"
+      overwrite = true
+    }
+  }
+}
+
+executor {
+    submitRateLimit = '5 sec'
+}
+
+// Process resource labels currently used by CloWM
+process {
+    executor = 'slurm'
+    container = 'ubuntu:22.04'
+    cpus   = { 2    }
+    memory = { 4000.MB }
+    maxErrors     = '-1'
+
+    // Process-specific resource requirements
+    withLabel:process_single {
+        cpus   = { 1 }
+        memory = { 6000.MB }
+    }
+    withLabel:process_low {
+        cpus   = { 2     }
+        memory = { 12000.MB }
+    }
+    withLabel:process_medium {
+        cpus   = { 6     }
+        memory = { 36000.MB }
+    }
+    withLabel:process_high {
+        cpus   = { 12    }
+        memory = { 72000.MB }
+    }
+    withLabel:process_high_memory {
+        memory = { 200000.MB }
+    }
+    withLabel:error_ignore {
+        errorStrategy = 'ignore'
+    }
+    withLabel: highmemXLarge {
+        cpus = { 28 }
+        memory = {470000.MB}
+    }
+    withLabel: computeXLarge {
+        cpus = {28}
+        memory = {470000.MB}
+    }
+    withLabel: highmemLarge {
+        cpus = {28}
+        memory = {240000.MB}
+    }
+    withLabel: highmemMedium {
+        cpus = {14}
+        memory = {120000.MB}
+    }
+    withLabel: large {
+        cpus = {28}
+        memory = {64000.MB}
+    }
+    withLabel: medium {
+        cpus = {14}
+        memory = {32000.MB}
+    }
+    withLabel: small {
+        cpus = {8}
+        memory = {16000.MB}
+    }
+    withLabel: mini {
+        cpus = {4}
+        memory = {8000.MB}
+    }
+    withLabel: tiny {
+        cpus = {1}
+        memory = {2000.MB}
+    }
+}`;
+  }
+  return `aws {
+    client {
+        endpoint = '${environment.S3_URL}'
+        s3PathStyleAccess = true
+    }
+    accessKey = '${s3KeyStore.keys[0]?.access_key ?? ""}'
+    secretKey = '${s3KeyStore.keys[0]?.secret_key ?? ""}'
+}
+
+docker {
+    enabled = true
+    runOptions = "-u \\$(id -u):\\$(id -g) -q"
+}
+
+// Disable unwanted features
+tower.enabled = false
+weblog.enabled = false
+shifter.enabled = false
+singularity.enabled = false
+podman.enabled = false
+charliecloud.enabled = false
+dag.enabled = true
+trace.enabled = true
+
+process {
+    executor = 'local'
+    container = 'ubuntu:22.04'
+    cpus   = { 2 }
+    memory = { 4000.MB }
+}
+`;
+});
+
+const configDownloadUrl = computed<string>(() =>
+  createDownloadUrl(nextflowConfig.value, "text/plain"),
+);
+
 function checkRepository() {
   formState.validated = true;
+  // remove trailing slash (/)
+  workflow.repository_url = workflow.repository_url
+    .trim()
+    .replace(/(^\/+|\/+$)/g, "");
   if (arbitraryWorkflowForm.value?.checkValidity() && !formState.allowUpload) {
     formState.unsupportedRepository = false;
     formState.missingFiles = [];
@@ -181,6 +386,7 @@ onMounted(() => {
   tokenHelpCollapse = new Collapse("#tokenHelpCollapse", {
     toggle: false,
   });
+  console.log(nextflowConfig.value);
 });
 </script>
 
@@ -188,12 +394,90 @@ onMounted(() => {
   <bootstrap-modal
     :modalId="modalId"
     :static-backdrop="false"
-    modal-label="Create Workflow Modal"
+    modal-label="Test My Workflow Modal"
     v-on="{ 'hidden.bs.modal': modalClosed }"
+    size-modifier-modal="lg"
   >
-    <template v-slot:header>Start arbitrary Workflow</template>
+    <template v-slot:header>Test workflow prior registration</template>
     <template v-slot:body>
+      <h5>Choose your execution environment</h5>
+      <div class="btn-group justify-content-center w-100 mb-2" role="group">
+        <input
+          type="radio"
+          class="btn-check"
+          name="execution-environment-choice"
+          id="clowm-outlined"
+          autocomplete="off"
+          checked
+          v-model="executionEnvironmentState.cli"
+          :value="false"
+        />
+        <label class="btn btn-outline-primary" for="clowm-outlined"
+          >CloWM native execution</label
+        >
+
+        <input
+          type="radio"
+          class="btn-check"
+          name="execution-environment-choice"
+          id="cli-outlined"
+          autocomplete="off"
+          v-model="executionEnvironmentState.cli"
+          :value="true"
+        />
+        <label class="btn btn-outline-primary" for="cli-outlined"
+          >Local Execution</label
+        >
+      </div>
+      <div v-if="executionEnvironmentState.cli">
+        <div class="btn-group justify-content-center w-100 mb-2" role="group">
+          <input
+            type="radio"
+            class="btn-check"
+            name="cluster-environment-choice"
+            id="laptop-outlined"
+            autocomplete="off"
+            checked
+            v-model="executionEnvironmentState.cluster"
+            :value="false"
+          />
+          <label class="btn btn-outline-primary" for="laptop-outlined"
+            >Personal computer</label
+          >
+
+          <input
+            type="radio"
+            class="btn-check"
+            name="cluster-environment-choice"
+            id="cluster-outlined"
+            autocomplete="off"
+            v-model="executionEnvironmentState.cluster"
+            :value="true"
+          />
+          <label class="btn btn-outline-primary" for="cluster-outlined"
+            >Emulated CloWM environment</label
+          >
+        </div>
+        <p v-if="executionEnvironmentState.cluster">
+          To emulate the CloWM native execution environment (e.g. docker
+          configuration, S3 access, resource labels etc.) on the workflow
+          development system, please download and use the Nextflow configuration
+          file (<code>clowm-nextflow.config</code>) as described below.
+        </p>
+        <p v-else>
+          To emulate a basic CloWM native execution environment (e.g. docker
+          configuration, S3 access etc.) on your personal computer, please
+          download and use the Nextflow configuration file
+          (<code>clowm-nextflow.config</code>) as described below.
+        </p>
+        <pre
+          class="rounded-1 w-100"
+        ><code>nextflow run /path/to/main.nf -c clowm-nextflow.config ...</code></pre>
+        <h6>clowm-nextflow.config:</h6>
+        <pre class="w-100 rounded-1"><code>{{ nextflowConfig }}</code></pre>
+      </div>
       <form
+        v-else
         id="arbitraryWorkflowForm"
         :class="{ 'was-validated': formState.validated }"
         ref="arbitraryWorkflowForm"
@@ -389,6 +673,7 @@ onMounted(() => {
     </template>
     <template v-slot:footer>
       <button
+        v-if="!executionEnvironmentState.cli"
         type="button"
         class="btn btn-info me-auto"
         @click="checkRepository"
@@ -406,6 +691,7 @@ onMounted(() => {
         Close
       </button>
       <button
+        v-if="!executionEnvironmentState.cli"
         type="submit"
         form="workflowCreateForm"
         class="btn btn-primary"
@@ -420,6 +706,16 @@ onMounted(() => {
         ></span>
         View
       </button>
+      <a
+        v-else
+        class="btn btn-primary"
+        role="button"
+        :href="configDownloadUrl"
+        download="clowm-nextflow.config"
+      >
+        Download config
+        <font-awesome-icon icon="fa-solid fa-download" class="ms-1" />
+      </a>
     </template>
   </bootstrap-modal>
 </template>
diff --git a/src/components/workflows/modals/CreateWorkflowModal.vue b/src/components/workflows/modals/CreateWorkflowModal.vue
index db2e210cb8163fe455f5e2d1352af40948d06df5..5eb0dd416bcad9e74601a3c1a3c1c1ceeab9c223 100644
--- a/src/components/workflows/modals/CreateWorkflowModal.vue
+++ b/src/components/workflows/modals/CreateWorkflowModal.vue
@@ -227,6 +227,10 @@ function checkRepository() {
   formState.validated = true;
   workflowRepositoryElement.value?.setCustomValidity("");
   workflowGitCommitHashElement.value?.setCustomValidity("");
+  // remove trailing slash (/)
+  workflow.repository_url = workflow.repository_url
+    .trim()
+    .replace(/(^\/+|\/+$)/g, "");
   if (workflowCreateForm.value?.checkValidity() && !formState.allowUpload) {
     formState.unsupportedRepository = false;
     formState.missingFiles = [];
diff --git a/src/views/workflows/ListWorkflowsView.vue b/src/views/workflows/ListWorkflowsView.vue
index d6167b396b94758200311c9e65cca1191ae0a9fc..9ee51bded4b9037152defb23bd4f65611b73fe54 100644
--- a/src/views/workflows/ListWorkflowsView.vue
+++ b/src/views/workflows/ListWorkflowsView.vue
@@ -39,7 +39,9 @@ const filterFunctionMapping: Record<
 
 function filterWorkflowByString(workflow: WorkflowOut): boolean {
   return workflowsState.filterString.length > 0
-    ? workflow.name.includes(workflowsState.filterString)
+    ? workflow.name
+        .toLowerCase()
+        .includes(workflowsState.filterString.toLowerCase())
     : true;
 }
 
diff --git a/src/views/workflows/MyWorkflowsView.vue b/src/views/workflows/MyWorkflowsView.vue
index 4f12f2e3eccad54ee9d738af27e0fccec1e2005b..9ad162d2b3c0af57da23e5dbff5083c690bfd68f 100644
--- a/src/views/workflows/MyWorkflowsView.vue
+++ b/src/views/workflows/MyWorkflowsView.vue
@@ -11,6 +11,8 @@ import UpdateWorkflowVersionIconModal from "@/components/workflows/modals/Update
 import UpdateWorkflowCredentialsModal from "@/components/workflows/modals/UpdateWorkflowCredentialsModal.vue";
 import { useWorkflowStore } from "@/stores/workflows";
 import { useWorkflowExecutionStore } from "@/stores/workflowExecutions";
+import { environment } from "@/environment";
+import ArbitraryWorkflowModal from "@/components/workflows/modals/ArbitraryWorkflowModal.vue";
 
 const workflowRepository = useWorkflowStore();
 const workflowExecutionRepository = useWorkflowExecutionStore();
@@ -131,6 +133,17 @@ onMounted(() => {
       Create
     </button>
   </div>
+  <div v-if="environment.DEV_SYSTEM" class="d-grid gap-2 col-4 mx-auto">
+    <button
+      class="btn btn-success btn-lg fs-3"
+      role="button"
+      data-bs-toggle="modal"
+      data-bs-target="#arbitraryWorkflowModal"
+    >
+      Test my Workflow
+    </button>
+    <arbitrary-workflow-modal modal-id="arbitraryWorkflowModal" />
+  </div>
   <div v-if="!workflowsState.loading">
     <card-transition-group
       v-if="sortedWorkflows.length > 0"