diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 13a22bf2ae1c1c3bf4432215639bbeecde193af5..239e44a8ec296809c16f4b11f06d941b79fa5aca 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -76,7 +76,7 @@ desktop_extension:package:release:
   script:
     - ./build-desktop.sh prod
   rules:
-    - if: $CI_COMMIT_BRANCH == "master" && $CI_COMMIT_TAG =~ /^(?:\d+\.){2}(?:\d+)$/
+    - if: $CI_COMMIT_BRANCH == "master" && $CI_COMMIT_TAG =~ "/^(?:\d+\.){2}(?:\d+)$/"
 
 desktop_extension:publish:release:
   stage: publish
@@ -93,4 +93,4 @@ desktop_extension:publish:release:
     - cd $EXTENSION_PATH
     - npm run vsce-publish -- -p $VSCODE_EXTENSION_MARKET_PLACE_ACCESS_TOKEN
   rules:
-    - if: $CI_COMMIT_BRANCH == "master" && $CI_COMMIT_TAG =~ /^(?:\d+\.){2}(?:\d+)$/
+    - if: $CI_COMMIT_BRANCH == "master" && $CI_COMMIT_TAG =~ "/^(?:\d+\.){2}(?:\d+)$/"
diff --git a/deadlock-plugins/deadlock-extension/package-lock.json b/deadlock-plugins/deadlock-extension/package-lock.json
index 5138863c0a71561d260f1100dc8bd5c200f9277c..83d3d20289067b19686a81c92f2a05633e1fb5d8 100644
--- a/deadlock-plugins/deadlock-extension/package-lock.json
+++ b/deadlock-plugins/deadlock-extension/package-lock.json
@@ -9,7 +9,6 @@
       "version": "0.1.11",
       "dependencies": {
         "@types/tar": "^6.1.1",
-        "@types/yaml": "^1.9.7",
         "@vscode/webview-ui-toolkit": "^1.0.0",
         "async": "^3.2.2",
         "axios": "^0.27.2",
@@ -28,7 +27,6 @@
         "@types/node-fetch": "^2.6.1",
         "@types/vscode": "^1.66.0",
         "@types/webpack": "^5.28.0",
-        "@types/webpack-dev-server": "^4.7.2",
         "@typescript-eslint/eslint-plugin": "^3.10.1",
         "@typescript-eslint/parser": "^3.10.1",
         "auto-changelog": "^2.4.0",
@@ -41,8 +39,9 @@
         "ts-loader": "^9.3.1",
         "typescript": "^4.7.2",
         "vsce": "^2.9.2",
-        "webpack": "^5.70.0",
-        "webpack-cli": "^4.10.0"
+        "webpack": "^5.73.0",
+        "webpack-cli": "^4.10.0",
+        "webpack-dev-server": "^4.9.3"
       },
       "engines": {
         "vscode": ">=1.66.0"
@@ -1454,9 +1453,9 @@
       }
     },
     "node_modules/@types/express-serve-static-core": {
-      "version": "4.17.28",
-      "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz",
-      "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==",
+      "version": "4.17.29",
+      "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.29.tgz",
+      "integrity": "sha512-uMd++6dMKS32EOuw1Uli3e3BPgdLIXmezcfHv7N4c1s3gkhikBplORPpMq3fuWkxncZN1reb16d5n8yhQ80x7Q==",
       "dev": true,
       "dependencies": {
         "@types/node": "*",
@@ -1656,16 +1655,6 @@
         "webpack": "^5"
       }
     },
-    "node_modules/@types/webpack-dev-server": {
-      "version": "4.7.2",
-      "resolved": "https://registry.npmjs.org/@types/webpack-dev-server/-/webpack-dev-server-4.7.2.tgz",
-      "integrity": "sha512-Y3p0Fmfvp0MHBDoCzo+xFJaWTw0/z37mWIo6P15j+OtmUDLvznJWdZNeD7Q004R+MpQlys12oXbXsrXRmxwg4Q==",
-      "deprecated": "This is a stub types definition. webpack-dev-server provides its own type definitions, so you do not need this installed.",
-      "dev": true,
-      "dependencies": {
-        "webpack-dev-server": "*"
-      }
-    },
     "node_modules/@types/ws": {
       "version": "8.5.3",
       "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz",
@@ -1675,15 +1664,6 @@
         "@types/node": "*"
       }
     },
-    "node_modules/@types/yaml": {
-      "version": "1.9.7",
-      "resolved": "https://registry.npmjs.org/@types/yaml/-/yaml-1.9.7.tgz",
-      "integrity": "sha512-8WMXRDD1D+wCohjfslHDgICd2JtMATZU8CkhH8LVJqcJs6dyYj5TGptzP8wApbmEullGBSsCEzzap73DQ1HJaA==",
-      "deprecated": "This is a stub types definition. yaml provides its own type definitions, so you do not need this installed.",
-      "dependencies": {
-        "yaml": "*"
-      }
-    },
     "node_modules/@types/yargs": {
       "version": "17.0.10",
       "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz",
@@ -2604,15 +2584,15 @@
       "dev": true
     },
     "node_modules/bonjour-service": {
-      "version": "1.0.12",
-      "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.0.12.tgz",
-      "integrity": "sha512-pMmguXYCu63Ug37DluMKEHdxc+aaIf/ay4YbF8Gxtba+9d3u+rmEWy61VK3Z3hp8Rskok3BunHYnG0dUHAsblw==",
+      "version": "1.0.13",
+      "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.0.13.tgz",
+      "integrity": "sha512-LWKRU/7EqDUC9CTAQtuZl5HzBALoCYwtLhffW3et7vZMwv3bWLpJf8bRYlMD5OCcDpTfnPgNCV4yo9ZIaJGMiA==",
       "dev": true,
       "dependencies": {
         "array-flatten": "^2.1.2",
         "dns-equal": "^1.0.0",
         "fast-deep-equal": "^3.1.3",
-        "multicast-dns": "^7.2.4"
+        "multicast-dns": "^7.2.5"
       }
     },
     "node_modules/boolbase": {
@@ -3158,9 +3138,9 @@
       "dev": true
     },
     "node_modules/connect-history-api-fallback": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
-      "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz",
+      "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==",
       "dev": true,
       "engines": {
         "node": ">=0.8"
@@ -3466,9 +3446,9 @@
       "dev": true
     },
     "node_modules/dns-packet": {
-      "version": "5.3.1",
-      "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.3.1.tgz",
-      "integrity": "sha512-spBwIj0TK0Ey3666GwIdWVfUpLyubpU53BTCu8iPn4r4oXd9O14Hjg3EHw3ts2oed77/SeckunUYCyRlSngqHw==",
+      "version": "5.4.0",
+      "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.4.0.tgz",
+      "integrity": "sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g==",
       "dev": true,
       "dependencies": {
         "@leichtgewicht/ip-codec": "^2.0.1"
@@ -4815,9 +4795,9 @@
       }
     },
     "node_modules/http-parser-js": {
-      "version": "0.5.6",
-      "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz",
-      "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==",
+      "version": "0.5.8",
+      "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz",
+      "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==",
       "dev": true
     },
     "node_modules/http-proxy": {
@@ -5045,6 +5025,21 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/is-docker": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+      "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+      "dev": true,
+      "bin": {
+        "is-docker": "cli.js"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/is-extglob": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -5168,21 +5163,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/is-wsl/node_modules/is-docker": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
-      "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
-      "dev": true,
-      "bin": {
-        "is-docker": "cli.js"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
     "node_modules/isarray": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@@ -6622,12 +6602,12 @@
       }
     },
     "node_modules/memfs": {
-      "version": "3.4.4",
-      "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.4.tgz",
-      "integrity": "sha512-W4gHNUE++1oSJVn8Y68jPXi+mkx3fXR5ITE/Ubz6EQ3xRpCN5k2CQ4AUR8094Z7211F876TyoBACGsIveqgiGA==",
+      "version": "3.4.7",
+      "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.7.tgz",
+      "integrity": "sha512-ygaiUSNalBX85388uskeCyhSAoOSgzBbtVCr9jA2RROssFL9Q19/ZXFqS+2Th2sr1ewNIWgFdLzLC3Yl1Zv+lw==",
       "dev": true,
       "dependencies": {
-        "fs-monkey": "1.0.3"
+        "fs-monkey": "^1.0.3"
       },
       "engines": {
         "node": ">= 4.0.0"
@@ -7182,21 +7162,6 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/open/node_modules/is-docker": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
-      "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
-      "dev": true,
-      "bin": {
-        "is-docker": "cli.js"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
     "node_modules/optionator": {
       "version": "0.9.1",
       "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
@@ -7804,7 +7769,7 @@
     "node_modules/requires-port": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
-      "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
+      "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
       "dev": true
     },
     "node_modules/resolve": {
@@ -7973,7 +7938,7 @@
     "node_modules/select-hose": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
-      "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
+      "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==",
       "dev": true
     },
     "node_modules/selfsigned": {
@@ -8060,7 +8025,7 @@
     "node_modules/serve-index": {
       "version": "1.9.1",
       "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
-      "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
+      "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==",
       "dev": true,
       "dependencies": {
         "accepts": "~1.3.4",
@@ -8129,7 +8094,7 @@
     "node_modules/serve-index/node_modules/statuses": {
       "version": "1.5.0",
       "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
-      "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
+      "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
       "dev": true,
       "engines": {
         "node": ">= 0.6"
@@ -9100,7 +9065,7 @@
     "node_modules/unpipe": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
-      "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
+      "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
       "dev": true,
       "engines": {
         "node": ">= 0.8"
@@ -9130,7 +9095,7 @@
     "node_modules/utils-merge": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
-      "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
+      "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
       "dev": true,
       "engines": {
         "node": ">= 0.4.0"
@@ -9176,7 +9141,7 @@
     "node_modules/vary": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
-      "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
+      "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
       "dev": true,
       "engines": {
         "node": ">= 0.8"
@@ -9303,9 +9268,9 @@
       "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
     },
     "node_modules/webpack": {
-      "version": "5.72.1",
-      "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.72.1.tgz",
-      "integrity": "sha512-dXG5zXCLspQR4krZVR6QgajnZOjW2K/djHvdcRaDQvsjV9z9vaW6+ja5dZOYbqBBjF6kGXka/2ZyxNdc+8Jung==",
+      "version": "5.73.0",
+      "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.73.0.tgz",
+      "integrity": "sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==",
       "dev": true,
       "dependencies": {
         "@types/eslint-scope": "^3.7.3",
@@ -9482,15 +9447,16 @@
       }
     },
     "node_modules/webpack-dev-server": {
-      "version": "4.9.1",
-      "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.9.1.tgz",
-      "integrity": "sha512-CTMfu2UMdR/4OOZVHRpdy84pNopOuigVIsRbGX3LVDMWNP8EUgC5mUBMErbwBlHTEX99ejZJpVqrir6EXAEajA==",
+      "version": "4.9.3",
+      "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.9.3.tgz",
+      "integrity": "sha512-3qp/eoboZG5/6QgiZ3llN8TUzkSpYg1Ko9khWX1h40MIEUNS2mDoIa8aXsPfskER+GbTvs/IJZ1QTBBhhuetSw==",
       "dev": true,
       "dependencies": {
         "@types/bonjour": "^3.5.9",
         "@types/connect-history-api-fallback": "^1.3.5",
         "@types/express": "^4.17.13",
         "@types/serve-index": "^1.9.1",
+        "@types/serve-static": "^1.13.10",
         "@types/sockjs": "^0.3.33",
         "@types/ws": "^8.5.1",
         "ansi-html-community": "^0.0.8",
@@ -9498,7 +9464,7 @@
         "chokidar": "^3.5.3",
         "colorette": "^2.0.10",
         "compression": "^1.7.4",
-        "connect-history-api-fallback": "^1.6.0",
+        "connect-history-api-fallback": "^2.0.0",
         "default-gateway": "^6.0.3",
         "express": "^4.17.3",
         "graceful-fs": "^4.2.6",
@@ -9522,6 +9488,10 @@
       "engines": {
         "node": ">= 12.13.0"
       },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      },
       "peerDependencies": {
         "webpack": "^4.37.0 || ^5.0.0"
       },
@@ -9753,9 +9723,9 @@
       }
     },
     "node_modules/ws": {
-      "version": "8.7.0",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-8.7.0.tgz",
-      "integrity": "sha512-c2gsP0PRwcLFzUiA8Mkr37/MI7ilIlHQxaEAtd0uNMbVMoy8puJyafRlm0bV9MbGSabUPeLrRRaqIBcFcA2Pqg==",
+      "version": "8.8.0",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.0.tgz",
+      "integrity": "sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ==",
       "dev": true,
       "engines": {
         "node": ">=10.0.0"
@@ -11034,9 +11004,9 @@
       }
     },
     "@types/express-serve-static-core": {
-      "version": "4.17.28",
-      "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz",
-      "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==",
+      "version": "4.17.29",
+      "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.29.tgz",
+      "integrity": "sha512-uMd++6dMKS32EOuw1Uli3e3BPgdLIXmezcfHv7N4c1s3gkhikBplORPpMq3fuWkxncZN1reb16d5n8yhQ80x7Q==",
       "dev": true,
       "requires": {
         "@types/node": "*",
@@ -11236,15 +11206,6 @@
         "webpack": "^5"
       }
     },
-    "@types/webpack-dev-server": {
-      "version": "4.7.2",
-      "resolved": "https://registry.npmjs.org/@types/webpack-dev-server/-/webpack-dev-server-4.7.2.tgz",
-      "integrity": "sha512-Y3p0Fmfvp0MHBDoCzo+xFJaWTw0/z37mWIo6P15j+OtmUDLvznJWdZNeD7Q004R+MpQlys12oXbXsrXRmxwg4Q==",
-      "dev": true,
-      "requires": {
-        "webpack-dev-server": "*"
-      }
-    },
     "@types/ws": {
       "version": "8.5.3",
       "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz",
@@ -11254,14 +11215,6 @@
         "@types/node": "*"
       }
     },
-    "@types/yaml": {
-      "version": "1.9.7",
-      "resolved": "https://registry.npmjs.org/@types/yaml/-/yaml-1.9.7.tgz",
-      "integrity": "sha512-8WMXRDD1D+wCohjfslHDgICd2JtMATZU8CkhH8LVJqcJs6dyYj5TGptzP8wApbmEullGBSsCEzzap73DQ1HJaA==",
-      "requires": {
-        "yaml": "*"
-      }
-    },
     "@types/yargs": {
       "version": "17.0.10",
       "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz",
@@ -11973,15 +11926,15 @@
       }
     },
     "bonjour-service": {
-      "version": "1.0.12",
-      "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.0.12.tgz",
-      "integrity": "sha512-pMmguXYCu63Ug37DluMKEHdxc+aaIf/ay4YbF8Gxtba+9d3u+rmEWy61VK3Z3hp8Rskok3BunHYnG0dUHAsblw==",
+      "version": "1.0.13",
+      "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.0.13.tgz",
+      "integrity": "sha512-LWKRU/7EqDUC9CTAQtuZl5HzBALoCYwtLhffW3et7vZMwv3bWLpJf8bRYlMD5OCcDpTfnPgNCV4yo9ZIaJGMiA==",
       "dev": true,
       "requires": {
         "array-flatten": "^2.1.2",
         "dns-equal": "^1.0.0",
         "fast-deep-equal": "^3.1.3",
-        "multicast-dns": "^7.2.4"
+        "multicast-dns": "^7.2.5"
       }
     },
     "boolbase": {
@@ -12391,9 +12344,9 @@
       "dev": true
     },
     "connect-history-api-fallback": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
-      "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz",
+      "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==",
       "dev": true
     },
     "console-control-strings": {
@@ -12622,9 +12575,9 @@
       "dev": true
     },
     "dns-packet": {
-      "version": "5.3.1",
-      "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.3.1.tgz",
-      "integrity": "sha512-spBwIj0TK0Ey3666GwIdWVfUpLyubpU53BTCu8iPn4r4oXd9O14Hjg3EHw3ts2oed77/SeckunUYCyRlSngqHw==",
+      "version": "5.4.0",
+      "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.4.0.tgz",
+      "integrity": "sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g==",
       "dev": true,
       "requires": {
         "@leichtgewicht/ip-codec": "^2.0.1"
@@ -13671,9 +13624,9 @@
       }
     },
     "http-parser-js": {
-      "version": "0.5.6",
-      "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz",
-      "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==",
+      "version": "0.5.8",
+      "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz",
+      "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==",
       "dev": true
     },
     "http-proxy": {
@@ -13834,6 +13787,12 @@
         "has": "^1.0.3"
       }
     },
+    "is-docker": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+      "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+      "dev": true
+    },
     "is-extglob": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -13913,14 +13872,6 @@
       "dev": true,
       "requires": {
         "is-docker": "^2.0.0"
-      },
-      "dependencies": {
-        "is-docker": {
-          "version": "2.2.1",
-          "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
-          "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
-          "dev": true
-        }
       }
     },
     "isarray": {
@@ -15031,12 +14982,12 @@
       "dev": true
     },
     "memfs": {
-      "version": "3.4.4",
-      "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.4.tgz",
-      "integrity": "sha512-W4gHNUE++1oSJVn8Y68jPXi+mkx3fXR5ITE/Ubz6EQ3xRpCN5k2CQ4AUR8094Z7211F876TyoBACGsIveqgiGA==",
+      "version": "3.4.7",
+      "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.7.tgz",
+      "integrity": "sha512-ygaiUSNalBX85388uskeCyhSAoOSgzBbtVCr9jA2RROssFL9Q19/ZXFqS+2Th2sr1ewNIWgFdLzLC3Yl1Zv+lw==",
       "dev": true,
       "requires": {
-        "fs-monkey": "1.0.3"
+        "fs-monkey": "^1.0.3"
       }
     },
     "merge-descriptors": {
@@ -15440,14 +15391,6 @@
         "define-lazy-prop": "^2.0.0",
         "is-docker": "^2.1.1",
         "is-wsl": "^2.2.0"
-      },
-      "dependencies": {
-        "is-docker": {
-          "version": "2.2.1",
-          "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
-          "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
-          "dev": true
-        }
       }
     },
     "optionator": {
@@ -15913,7 +15856,7 @@
     "requires-port": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
-      "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
+      "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
       "dev": true
     },
     "resolve": {
@@ -16035,7 +15978,7 @@
     "select-hose": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
-      "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
+      "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==",
       "dev": true
     },
     "selfsigned": {
@@ -16114,7 +16057,7 @@
     "serve-index": {
       "version": "1.9.1",
       "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
-      "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
+      "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==",
       "dev": true,
       "requires": {
         "accepts": "~1.3.4",
@@ -16174,7 +16117,7 @@
         "statuses": {
           "version": "1.5.0",
           "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
-          "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
+          "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
           "dev": true
         }
       }
@@ -16893,7 +16836,7 @@
     "unpipe": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
-      "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
+      "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
       "dev": true
     },
     "uri-js": {
@@ -16920,7 +16863,7 @@
     "utils-merge": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
-      "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
+      "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
       "dev": true
     },
     "uuid": {
@@ -16957,7 +16900,7 @@
     "vary": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
-      "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
+      "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
       "dev": true
     },
     "vsce": {
@@ -17062,9 +17005,9 @@
       "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
     },
     "webpack": {
-      "version": "5.72.1",
-      "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.72.1.tgz",
-      "integrity": "sha512-dXG5zXCLspQR4krZVR6QgajnZOjW2K/djHvdcRaDQvsjV9z9vaW6+ja5dZOYbqBBjF6kGXka/2ZyxNdc+8Jung==",
+      "version": "5.73.0",
+      "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.73.0.tgz",
+      "integrity": "sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==",
       "dev": true,
       "requires": {
         "@types/eslint-scope": "^3.7.3",
@@ -17176,15 +17119,16 @@
       }
     },
     "webpack-dev-server": {
-      "version": "4.9.1",
-      "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.9.1.tgz",
-      "integrity": "sha512-CTMfu2UMdR/4OOZVHRpdy84pNopOuigVIsRbGX3LVDMWNP8EUgC5mUBMErbwBlHTEX99ejZJpVqrir6EXAEajA==",
+      "version": "4.9.3",
+      "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.9.3.tgz",
+      "integrity": "sha512-3qp/eoboZG5/6QgiZ3llN8TUzkSpYg1Ko9khWX1h40MIEUNS2mDoIa8aXsPfskER+GbTvs/IJZ1QTBBhhuetSw==",
       "dev": true,
       "requires": {
         "@types/bonjour": "^3.5.9",
         "@types/connect-history-api-fallback": "^1.3.5",
         "@types/express": "^4.17.13",
         "@types/serve-index": "^1.9.1",
+        "@types/serve-static": "^1.13.10",
         "@types/sockjs": "^0.3.33",
         "@types/ws": "^8.5.1",
         "ansi-html-community": "^0.0.8",
@@ -17192,7 +17136,7 @@
         "chokidar": "^3.5.3",
         "colorette": "^2.0.10",
         "compression": "^1.7.4",
-        "connect-history-api-fallback": "^1.6.0",
+        "connect-history-api-fallback": "^2.0.0",
         "default-gateway": "^6.0.3",
         "express": "^4.17.3",
         "graceful-fs": "^4.2.6",
@@ -17384,9 +17328,9 @@
       }
     },
     "ws": {
-      "version": "8.7.0",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-8.7.0.tgz",
-      "integrity": "sha512-c2gsP0PRwcLFzUiA8Mkr37/MI7ilIlHQxaEAtd0uNMbVMoy8puJyafRlm0bV9MbGSabUPeLrRRaqIBcFcA2Pqg==",
+      "version": "8.8.0",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.0.tgz",
+      "integrity": "sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ==",
       "dev": true,
       "requires": {}
     },
diff --git a/deadlock-plugins/deadlock-extension/package.json b/deadlock-plugins/deadlock-extension/package.json
index 7b58b5ba4cc7fe53111d747680eff2b47617df80..fa446a0418c18ca882be8e71a29ee6499939a0f8 100644
--- a/deadlock-plugins/deadlock-extension/package.json
+++ b/deadlock-plugins/deadlock-extension/package.json
@@ -98,7 +98,6 @@
   },
   "dependencies": {
     "@types/tar": "^6.1.1",
-    "@types/yaml": "^1.9.7",
     "@vscode/webview-ui-toolkit": "^1.0.0",
     "async": "^3.2.2",
     "axios": "^0.27.2",
@@ -117,7 +116,6 @@
     "@types/node-fetch": "^2.6.1",
     "@types/vscode": "^1.66.0",
     "@types/webpack": "^5.28.0",
-    "@types/webpack-dev-server": "^4.7.2",
     "@typescript-eslint/eslint-plugin": "^3.10.1",
     "@typescript-eslint/parser": "^3.10.1",
     "auto-changelog": "^2.4.0",
@@ -130,8 +128,9 @@
     "ts-loader": "^9.3.1",
     "typescript": "^4.7.2",
     "vsce": "^2.9.2",
-    "webpack": "^5.70.0",
-    "webpack-cli": "^4.10.0"
+    "webpack": "^5.73.0",
+    "webpack-cli": "^4.10.0",
+    "webpack-dev-server": "^4.9.3"
   },
   "extensionPack": [
     "ms-vscode-remote.remote-containers"
diff --git a/deadlock-plugins/deadlock-extension/src/core/api.service.ts b/deadlock-plugins/deadlock-extension/src/core/api.service.ts
index 116dfceb286b9e29019acedd9a29b01ea2ba1745..736867962bf0dffa2535cfe081be119b7d1784e7 100644
--- a/deadlock-plugins/deadlock-extension/src/core/api.service.ts
+++ b/deadlock-plugins/deadlock-extension/src/core/api.service.ts
@@ -7,15 +7,20 @@ import Controller from './controller';
 import ExtensionStore from './extensionStore';
 import KeycloakOAuth2DeviceFlowConnection from './keycloakOAuth2DeviceFlowConnection';
 import { MissionUser } from './mission/model/missionUser';
-import { User } from './mission/model/userMission';
+import UserMission, { User } from './mission/model/userMission';
 
 export default class ApiService {
   private axiosInstance: AxiosInstance;
-  constructor(
-    private keycloackConnection: KeycloakOAuth2DeviceFlowConnection,
-    private extensionStore: ExtensionStore,
-    private controller: Controller,
-  ) {
+  private static _instance: ApiService;
+
+  static getInstance(): ApiService {
+    if (!ApiService._instance) {
+      ApiService._instance = new ApiService();
+    }
+    return ApiService._instance;
+  }
+
+  private constructor() {
     this.axiosInstance = axios.create({
       baseURL: API_URL,
       headers: {
@@ -27,6 +32,18 @@ export default class ApiService {
     this.initApiInterceptor();
   }
 
+  private get controller(): Controller {
+    return Controller.getInstance();
+  }
+
+  private get extensionStore(): ExtensionStore {
+    return ExtensionStore.getInstance();
+  }
+
+  private get keycloackConnection(): KeycloakOAuth2DeviceFlowConnection {
+    return KeycloakOAuth2DeviceFlowConnection.getInstance();
+  }
+
   initApiInterceptor() {
     this.initRequestInterceptor();
     this.initResponseInterceptor();
@@ -140,19 +157,25 @@ export default class ApiService {
       .then((res) => res.status);
   }
 
-  async pingUpdateWorkTime(userId: string, missionId: string): Promise<MissionUser> {
+  async pingUpdateWorkTime(): Promise<MissionUser> {
     return this.axiosInstance
-      .post<MissionUser>(`users/${userId}/missions/${missionId}/worktime`, {
-        action: 'PING',
-      })
+      .post<MissionUser>(
+        `users/${(await this.getCurrentUser()).id}/missions/${UserMission.getInstance().missionId}/worktime`,
+        {
+          action: 'PING',
+        },
+      )
       .then((res) => res.data);
   }
 
-  async startUpdateWorkTime(userId: string, missionId: string): Promise<MissionUser> {
+  async startUpdateWorkTime(): Promise<MissionUser> {
     return this.axiosInstance
-      .post<MissionUser>(`users/${userId}/missions/${missionId}/worktime`, {
-        action: 'START',
-      })
+      .post<MissionUser>(
+        `users/${(await this.getCurrentUser()).id}/missions/${UserMission.getInstance().missionId}/worktime`,
+        {
+          action: 'START',
+        },
+      )
       .then((res) => res.data);
   }
 }
diff --git a/deadlock-plugins/deadlock-extension/src/core/commandHandler.ts b/deadlock-plugins/deadlock-extension/src/core/commandHandler.ts
index cf1e95717c0fda9cb5ca9382790fa8a501c80039..6dde3a57fc7f225dabfdafd7b9cc27ad107ce2c9 100644
--- a/deadlock-plugins/deadlock-extension/src/core/commandHandler.ts
+++ b/deadlock-plugins/deadlock-extension/src/core/commandHandler.ts
@@ -1,5 +1,4 @@
-import { commands } from 'vscode';
-import { VsCommand } from '../theia/command';
+import { Command, commands } from 'vscode';
 import Controller from './controller';
 export class CommandHandler {
   constructor(private controller: Controller) {
@@ -7,11 +6,11 @@ export class CommandHandler {
   }
 
   initCommandHandler() {
-    commands.registerCommand(disconnectCommand.cmd, this.controller.disconnect.bind(this.controller));
-    commands.registerCommand(authenticateCommand.cmd, this.controller.authenticate.bind(this.controller));
+    commands.registerCommand(disconnectCommand.command, this.controller.disconnect.bind(this.controller));
+    commands.registerCommand(authenticateCommand.command, this.controller.authenticate.bind(this.controller));
   }
 }
 
-export const disconnectCommand = new VsCommand('Disconnect', 'deadlock.disconnect');
-export const authenticateCommand = new VsCommand('Authenticate', 'deadlock.authenticate');
-export const openUrlInBrowserCommand = new VsCommand('Open url in browser', 'vscode.open');
+export const disconnectCommand: Command = { title: 'Disconnect', command: 'deadlock.disconnect' };
+export const authenticateCommand: Command = { title: 'Authenticate', command: 'deadlock.authenticate' };
+export const openUrlInBrowserCommand: Command = { title: 'Open url in browser', command: 'vscode.open' };
diff --git a/deadlock-plugins/deadlock-extension/src/core/config.ts b/deadlock-plugins/deadlock-extension/src/core/config.ts
index 50d2bb53c07b28a229e2729de7d57efe727f38b9..7c9e0f06f4494aec60d6e282b0f170be66f77970 100644
--- a/deadlock-plugins/deadlock-extension/src/core/config.ts
+++ b/deadlock-plugins/deadlock-extension/src/core/config.ts
@@ -1,37 +1,30 @@
-import * as os from 'os';
-import * as path from 'path';
+import { homedir } from 'os';
+import { join } from 'path';
 import isDocker from './utils/isdocker';
 
-const homeDir = os.homedir();
 // if we are on container, means the directory will depend differently
 const onContainer = isDocker();
 
-// TODO: remove this next line
-const deadlockExtensionPath = path.join(homeDir, 'deadlock-extension');
+const deadlockConfigPath = join(homedir(), '.deadlock');
 
-const deadlockConfigPath = path.join(homeDir, '.deadlock');
-export const userSshKeyFolderPath = path.join(deadlockConfigPath, '.ssh');
-export const missionWorkdir = path.join(deadlockConfigPath, 'workspace');
+export const userSshKeyFolderPath = join(deadlockConfigPath, '.ssh');
 
-export const PROJECT_SRC_PATH = onContainer ? '/project' : path.join(homeDir, 'deadlock-extension', '/project');
+export const DOCS_PATH_IC = `${homedir()}/docs`;
 
-// TODO: remove this next line (theia????)
-export const PROJECT_DEADLOCK_DESKTOP_PATH = onContainer
-  ? path.join('/home/deadlock/mission')
-  : path.join(deadlockExtensionPath, 'project-theia');
+export const missionWorkdir = join(deadlockConfigPath, 'workspace');
 
-export const DOCS_PATH = path.join(path.join(onContainer ? '/home/deadlock' : deadlockExtensionPath), 'docs');
+export const GITEA_PATH_IC = '/project';
 
-export const DEADLOCK_WORKDIR_PATH = onContainer ? '/deadlock' : deadlockConfigPath;
+export const MISSION_PATH_IC = `${homedir()}/mission`;
 
-export const CONFIG_PATH = onContainer ? '/home/config/' : path.join(deadlockExtensionPath, 'config');
+export const DEADLOCK_WORKDIR_PATH = onContainer ? '/deadlock' : deadlockConfigPath;
 
-export const USER_CHALLENGE_PATH = path.join(CONFIG_PATH, 'user-challenge.json');
+export const USER_MISSION_PATH = join('/home/config/user-challenge.json');
 
 export const BRIEFING_FILE_NAME = 'briefing.md';
 
-export const ENV_FILE_PATH = path.join(PROJECT_DEADLOCK_DESKTOP_PATH, '/.env');
+export const ENV_FILE_PATH = join(MISSION_PATH_IC, '.env');
 
-export const BASHRC_PATH = path.join(homeDir, '/.bashrc');
+export const BASHRC_PATH = join(homedir(), '.bashrc');
 
-export const SERVICES_PATHS_PATH = path.join(PROJECT_DEADLOCK_DESKTOP_PATH, '/paths.json');
+export const SERVICES_PATHS_PATH = join(MISSION_PATH_IC, 'paths.json');
diff --git a/deadlock-plugins/deadlock-extension/src/core/controller.ts b/deadlock-plugins/deadlock-extension/src/core/controller.ts
index 55e4fd2fd8459c44d86d070f15d06655a37db636..8f7f779fb93f4c2e56b0e5e2f737df5f80670231 100644
--- a/deadlock-plugins/deadlock-extension/src/core/controller.ts
+++ b/deadlock-plugins/deadlock-extension/src/core/controller.ts
@@ -1,57 +1,48 @@
-import { KEYCLOAK_DEVICE_AUTH_URL, KEYCLOAK_TOKEN_CREATE_URL, KEYCLOAK_USER_INFO_URL } from '../config';
 import BriefingView from '../view/briefingView';
 import QuickSetupView from '../view/quickSetupView';
 import { CommandHandler, openUrlInBrowserCommand } from './commandHandler';
 import ExtensionStore from './extensionStore';
 import KeycloakOAuth2DeviceFlowConnection from './keycloakOAuth2DeviceFlowConnection';
-import ApiService from './api.service';
-import { GiteaPublicProperties } from '../model/giteaPublicProperties.model';
 import { MissionDevContainer } from './mission/missionDevContainer';
 import { extensionError, extensionLog as log, extensionWarn } from '../recorder/utils/log';
-import { commands, ExtensionContext, Uri, window } from 'vscode';
+import { Command, commands, ExtensionContext, Uri, window } from 'vscode';
 import { createSshKeyFiles } from './sshKeyManager';
 import { emptyDirectories, removeFilesOrDirectories } from '../recorder/utils/workdir';
 import { missionWorkdir, userSshKeyFolderPath } from './config';
 import { hasStatusNumber } from './utils/typeguards';
-import { User } from './mission/model/userMission';
-import { existsSync, mkdirSync, writeFileSync } from 'fs';
+import { existsSync, mkdirSync, readdirSync, renameSync, rmSync, writeFileSync } from 'fs';
 import { extract } from 'tar';
 import { parse } from 'yaml';
 import isDocker from './utils/isdocker';
-import * as fs from 'fs';
 import { getReviewedStudentWorkdirPath } from './utils/mission.utils';
 import { join } from 'path';
 import Mission from '../model/mission';
+import ApiService from './api.service';
 
 export default class Controller {
   private static instance: Controller;
-  public connection: KeycloakOAuth2DeviceFlowConnection;
   private commandHandler: CommandHandler;
   private briefingView: BriefingView;
   private quickSetupView: QuickSetupView;
-  private _apiService: ApiService;
   private _extensionStore: ExtensionStore;
 
   public get extensionStore() {
     return this._extensionStore;
   }
 
-  public get apiService() {
-    return this._apiService;
+  private get connection(): KeycloakOAuth2DeviceFlowConnection {
+    return KeycloakOAuth2DeviceFlowConnection.getInstance();
   }
 
-  private constructor(context: ExtensionContext) {
+  private get apiService(): ApiService {
+    return ApiService.getInstance();
+  }
+
+  private constructor(public readonly context: ExtensionContext) {
     this._extensionStore = ExtensionStore.getInstance(context);
     this.briefingView = new BriefingView();
     this.quickSetupView = new QuickSetupView(context.extensionUri);
     this.commandHandler = new CommandHandler(this);
-    this.connection = new KeycloakOAuth2DeviceFlowConnection(
-      KEYCLOAK_DEVICE_AUTH_URL,
-      KEYCLOAK_TOKEN_CREATE_URL,
-      KEYCLOAK_USER_INFO_URL,
-    );
-
-    this._apiService = new ApiService(this.connection, this._extensionStore, this);
 
     this.init();
   }
@@ -74,13 +65,13 @@ export default class Controller {
 
   public async getSolution(missionId: string, reviewedId: string) {
     try {
-      const solution = await this._apiService.getSolution(missionId);
+      const solution = await this.apiService.getSolution(missionId);
       const solutionFolder = join(getReviewedStudentWorkdirPath(reviewedId), missionId, '.solution');
       const tarName = 'solution.tar.gz';
       const tarPath = join(solutionFolder, tarName);
 
       if (existsSync(solutionFolder)) {
-        fs.rmSync(solutionFolder, { recursive: true });
+        rmSync(solutionFolder, { recursive: true });
       }
 
       mkdirSync(solutionFolder, { recursive: true });
@@ -89,10 +80,10 @@ export default class Controller {
       extract({ sync: true, file: `${solutionFolder}/${tarName}`, cwd: solutionFolder });
       await removeFilesOrDirectories(`${solutionFolder}/${tarName}`);
       // list files in the folder
-      fs.readdirSync(solutionFolder).forEach((file) => {
+      readdirSync(solutionFolder).forEach((file) => {
         const tmpSolutionPath = join(solutionFolder, file);
-        fs.readdirSync(tmpSolutionPath).map((f) => fs.renameSync(join(tmpSolutionPath, f), join(solutionFolder, f)));
-        fs.rmSync(tmpSolutionPath, { recursive: true });
+        readdirSync(tmpSolutionPath).map((f) => renameSync(join(tmpSolutionPath, f), join(solutionFolder, f)));
+        rmSync(tmpSolutionPath, { recursive: true });
       });
     } catch (e) {
       window.showErrorMessage(`Une erreur est survenue lors de la récupération de la solution`);
@@ -154,7 +145,7 @@ export default class Controller {
   }
 
   public async createSshKeyPair() {
-    const { publicKey, privateKey } = await this._apiService.getUserSshKey();
+    const { publicKey, privateKey } = await this.apiService.getUserSshKey();
     await createSshKeyFiles(publicKey, privateKey);
   }
 
@@ -168,10 +159,10 @@ export default class Controller {
   }
 
   public static openBrowserWithUrl(url: string) {
-    commands.executeCommand(openUrlInBrowserCommand.cmd, Uri.parse(url));
+    commands.executeCommand(openUrlInBrowserCommand.command, Uri.parse(url));
   }
 
-  public async launchMission(missionId: string, missionVersion: string, userId?: string) {
+  public async launchMission(missionId: string, missionVersion: string, revieweeId?: string) {
     window.showInformationMessage(`vous lancez la mission ${missionId}`);
 
     const hadBeenConnected = (await this._extensionStore.getAccessToken()) !== undefined;
@@ -181,13 +172,11 @@ export default class Controller {
       window.showInformationMessage('Connexion validée');
     }
 
-    const currentUser = await this.apiService.getCurrentUser();
+    const reviewer = await this.apiService.getCurrentUser();
 
-    const user: User = userId ? await this._apiService.getUser(userId) : currentUser;
-
-    if (!!userId && userId !== currentUser.id) {
+    if (!!revieweeId && revieweeId !== reviewer.id) {
       try {
-        await this._apiService.grantAccessToRepository(user.id, missionId);
+        await this.apiService.grantAccessToRepository(revieweeId, missionId);
       } catch (e) {
         if (hasStatusNumber(e)) {
           if (e.status === 403) {
@@ -199,22 +188,14 @@ export default class Controller {
         }
       }
       try {
-        await Controller.getInstance().getSolution(missionId, user.id);
+        await Controller.getInstance().getSolution(missionId, revieweeId);
       } catch (e) {
         window.showErrorMessage(`Une erreur est survenue lors de la récupération de la solution`);
         extensionError(e);
       }
     }
 
-    const giteaPublicProperties: GiteaPublicProperties = await this._apiService.getGiteaPublicProperties();
-
-    const missionDevcontainer = new MissionDevContainer(
-      user,
-      currentUser,
-      missionId,
-      missionVersion,
-      giteaPublicProperties,
-    );
+    const missionDevcontainer = new MissionDevContainer(missionId, missionVersion, revieweeId);
 
     try {
       await missionDevcontainer.open();
@@ -223,3 +204,13 @@ export default class Controller {
     }
   }
 }
+
+export const openBriefingCommand: Command = {
+  title: 'Open Briefing',
+  command: 'deadlock.openBriefing',
+};
+
+export const openQuickSetupCommand: Command = {
+  title: 'Open Deadlock quick setup page',
+  command: 'deadlock.openQuickSetup',
+};
diff --git a/deadlock-plugins/deadlock-extension/src/core/gitMission.ts b/deadlock-plugins/deadlock-extension/src/core/gitMission.ts
index ae085a23b6a5c2a722fced9b12a914d87fc55c13..090179977aee35aefc74bf80699ab398e71576ab 100644
--- a/deadlock-plugins/deadlock-extension/src/core/gitMission.ts
+++ b/deadlock-plugins/deadlock-extension/src/core/gitMission.ts
@@ -1,27 +1,24 @@
 import { exec as execCallback } from 'child_process';
 import simpleGit, { SimpleGit, SimpleGitOptions } from 'simple-git';
-import { PROJECT_SRC_PATH } from './config';
-import UserConfig from './userConfig';
+import { GITEA_PATH_IC } from './config';
 import { log as customizableLog, error as customizableError } from '../recorder/utils/log';
 import { promisify } from 'util';
+import UserMission from './mission/model/userMission';
+import ApiService from './api.service';
 
 const exec = promisify(execCallback);
 
 const defaultRemote = 'origin';
 
-export enum Branch {
-  MASTER = 'master',
-  DEFAULT = MASTER,
-  LIVE = 'live',
-}
+type Branch = 'master' | 'live';
 
 export default class GitMission {
   private prefix = 'DEADLOCK-RECORDER';
   private git: SimpleGit;
 
-  constructor(private userConfig: UserConfig) {
+  constructor() {
     const options: Partial<SimpleGitOptions> = {
-      baseDir: PROJECT_SRC_PATH,
+      baseDir: GITEA_PATH_IC,
       binary: 'git',
       maxConcurrentProcesses: 2,
     };
@@ -39,10 +36,9 @@ export default class GitMission {
 
   async setupSshAgent() {
     try {
+      const gitea = await ApiService.getInstance().getGiteaPublicProperties();
       await exec(`ssh-add /tmp/.ssh/id_rsa`);
-      await exec(
-        `eval "$(ssh-agent -s)" && ssh-keyscan -p ${this.userConfig.userConfigJson.giteaSshPort} -H ${this.userConfig.userConfigJson.giteaHost} >> ~/.ssh/known_hosts`,
-      );
+      await exec(`eval "$(ssh-agent -s)" && ssh-keyscan -p ${gitea.sshPort} -H ${gitea.sshHost} >> ~/.ssh/known_hosts`);
     } catch (err) {
       this.log(err);
       if (err instanceof Error) {
@@ -57,8 +53,8 @@ export default class GitMission {
     }
   }
 
-  get author() {
-    return this.userConfig.userConfigJson.username;
+  async getAuthor(): Promise<string> {
+    return (await UserMission.getInstance().getGiteaUser()).username;
   }
 
   async init() {
@@ -73,22 +69,17 @@ export default class GitMission {
         return Promise.resolve(this);
       }
 
-      const remotePath = this.getRemotePath();
+      const giteaUser = await UserMission.getInstance().getGiteaUser();
 
-      await this.git.addRemote(defaultRemote, remotePath);
-      await this.git.addConfig('user.email', this.userConfig.userConfigJson.email, false, 'local');
+      await this.git.addRemote(defaultRemote, await this.getRemotePath());
+      await this.git.addConfig('user.email', await UserMission.getInstance().getEmail(), false, 'local');
       await this.git.addConfig(
         'user.name',
-        `${this.userConfig.userConfigJson.currentUserDetails.lastName} ${this.userConfig.userConfigJson.currentUserDetails.firstName}`,
+        `${giteaUser.details.lastName} ${giteaUser.details.firstName}`,
         false,
         'local',
       );
-      await this.git.addConfig(
-        'core.excludesFile',
-        `user-git-${this.userConfig!.userConfigJson.username}/\n`,
-        true,
-        'local',
-      );
+      await this.git.addConfig('core.excludesFile', `user-git-${giteaUser.username}/\n`, true, 'local');
 
       return Promise.resolve(this);
     } catch (e) {
@@ -97,8 +88,11 @@ export default class GitMission {
     }
   }
 
-  private getRemotePath() {
-    return `ssh://git@${this.userConfig.userConfigJson.giteaHost}:${this.userConfig.userConfigJson.giteaSshPort}/${this.userConfig.userConfigJson.remoteGitUsername}/${this.userConfig.userConfigJson.missionId}`;
+  private async getRemotePath() {
+    const giteaConfig = await ApiService.getInstance().getGiteaPublicProperties();
+    return `ssh://git@${giteaConfig.sshHost}:${giteaConfig.sshPort}/${
+      (await UserMission.getInstance().getGiteaUser()).username
+    }/${UserMission.getInstance().missionId}`;
   }
 
   async readRemote() {
@@ -114,8 +108,8 @@ export default class GitMission {
     return this.git.fetch(defaultRemote);
   }
 
-  pull(branch?: string) {
-    return this.git.pull(defaultRemote, branch ?? Branch.DEFAULT, { '--rebase': 'true' });
+  pull(branch: Branch = 'master') {
+    return this.git.pull(defaultRemote, branch, { '--rebase': 'true' });
   }
 
   addAll() {
@@ -130,26 +124,26 @@ export default class GitMission {
     return this.git.push(defaultRemote);
   }
 
-  createLocalBranch(branch: string) {
+  createLocalBranch(branch: Branch = 'master') {
     return this.git.checkout(['-b', branch]);
   }
 
-  createRemoteBranch(branch: string) {
+  createRemoteBranch(branch: Branch = 'master') {
     return this.git.push(['-u', defaultRemote, branch]);
   }
 
-  setUpstream(branch: string) {
+  setUpstream(branch: Branch = 'master') {
     return this.git.branch(['-u', defaultRemote, branch]);
   }
 
-  createBranch(branch: string) {
+  createBranch(branch: Branch = 'master') {
     const createBranchLocally = this.createLocalBranch(branch);
     const createRemoteBranch = this.createRemoteBranch(branch);
 
     return Promise.all([createBranchLocally, createRemoteBranch]);
   }
 
-  checkout(branch: string) {
+  checkout(branch: Branch = 'master') {
     return this.git.checkout(branch);
   }
 
diff --git a/deadlock-plugins/deadlock-extension/src/core/keycloakOAuth2DeviceFlowConnection.test.ts b/deadlock-plugins/deadlock-extension/src/core/keycloakOAuth2DeviceFlowConnection.test.ts
index 3d97d9aaaf128e86afed34ff20533a39992a95ad..5f690680e760fcd019286f66df71552ae885f15d 100644
--- a/deadlock-plugins/deadlock-extension/src/core/keycloakOAuth2DeviceFlowConnection.test.ts
+++ b/deadlock-plugins/deadlock-extension/src/core/keycloakOAuth2DeviceFlowConnection.test.ts
@@ -1,5 +1,4 @@
 import { Response } from 'node-fetch';
-import { KEYCLOAK_DEVICE_AUTH_URL, KEYCLOAK_TOKEN_CREATE_URL, KEYCLOAK_USER_INFO_URL } from '../config';
 import KeycloakOAuth2DeviceFlowConnection from '../core/keycloakOAuth2DeviceFlowConnection';
 import { setConnected, setPending, setRefused, test_token } from '../test/service/mocks/handlers';
 
@@ -51,10 +50,6 @@ describe('KeycloakOAuth2DeviceFlowConnection', () => {
   });
 
   beforeEach(async () => {
-    connection = new KeycloakOAuth2DeviceFlowConnection(
-      KEYCLOAK_DEVICE_AUTH_URL,
-      KEYCLOAK_TOKEN_CREATE_URL,
-      KEYCLOAK_USER_INFO_URL,
-    );
+    connection = new KeycloakOAuth2DeviceFlowConnection();
   });
 });
diff --git a/deadlock-plugins/deadlock-extension/src/core/keycloakOAuth2DeviceFlowConnection.ts b/deadlock-plugins/deadlock-extension/src/core/keycloakOAuth2DeviceFlowConnection.ts
index c31dd69b76ecff4f0d91abbfa400393fbf526aa2..587f973416f5976fa3af5c2e99b1ba62b31791d3 100644
--- a/deadlock-plugins/deadlock-extension/src/core/keycloakOAuth2DeviceFlowConnection.ts
+++ b/deadlock-plugins/deadlock-extension/src/core/keycloakOAuth2DeviceFlowConnection.ts
@@ -1,7 +1,12 @@
 import * as https from 'https';
 import { Response } from 'node-fetch';
 import fetch from 'node-fetch';
-import { REJECT_UNAUTHORIZED } from '../config';
+import {
+  KEYCLOAK_DEVICE_AUTH_URL,
+  KEYCLOAK_TOKEN_CREATE_URL,
+  KEYCLOAK_USER_INFO_URL,
+  REJECT_UNAUTHORIZED,
+} from '../config';
 import { HttpStatusCode } from '../customTypings/HttpStatusCode';
 import { TokenFetchErrorCode } from '../customTypings/KeycloakAPITypes';
 import { extensionError as err, extensionLog as log } from '../recorder/utils/log';
@@ -13,8 +18,9 @@ export default class KeycloakOAuth2DeviceFlowConnection {
   private accessToken: string;
   private refreshToken: string;
   private deviceAuthorizationRequestResponse: DeviceAuthorizationRequestResponse;
+  private static _instance: KeycloakOAuth2DeviceFlowConnection;
 
-  constructor(private deviceUrl: string, private tokenUrl: string, private userInfoUrl: string) {
+  constructor() {
     /*
      * Arbitrary durations to wait in seconds \
      * Waiting time between requests should be increasing
@@ -29,6 +35,13 @@ export default class KeycloakOAuth2DeviceFlowConnection {
     this.deviceAuthorizationRequestResponse = {};
   }
 
+  public static getInstance(): KeycloakOAuth2DeviceFlowConnection {
+    if (!KeycloakOAuth2DeviceFlowConnection._instance) {
+      KeycloakOAuth2DeviceFlowConnection._instance = new KeycloakOAuth2DeviceFlowConnection();
+    }
+    return KeycloakOAuth2DeviceFlowConnection._instance;
+  }
+
   /**
    * @param accessToken
    * @returns Promise
@@ -37,7 +50,8 @@ export default class KeycloakOAuth2DeviceFlowConnection {
     if (!accessToken) {
       return Promise.resolve(false);
     }
-    const tokenValidationRequestResponse: Response = await fetch(this.userInfoUrl, {
+
+    const tokenValidationRequestResponse: Response = await fetch(KEYCLOAK_USER_INFO_URL, {
       method: 'POST',
       headers: {
         'Content-Type': 'application/x-www-form-urlencoded',
@@ -71,7 +85,7 @@ export default class KeycloakOAuth2DeviceFlowConnection {
     if (refreshToken !== undefined) {
       await this.createUserAuthentication(
         {
-          url: this.tokenUrl,
+          url: KEYCLOAK_TOKEN_CREATE_URL,
           body: (() => {
             const params = new URLSearchParams();
             params.append('response_type', 'token');
@@ -93,7 +107,7 @@ export default class KeycloakOAuth2DeviceFlowConnection {
       openLink(this.deviceAuthorizationRequestResponse.verification_uri_complete!);
       await this.createUserAuthentication(
         {
-          url: this.tokenUrl,
+          url: KEYCLOAK_TOKEN_CREATE_URL,
           body: (() => {
             const params = new URLSearchParams();
             params.append('response_type', 'token');
@@ -118,7 +132,7 @@ export default class KeycloakOAuth2DeviceFlowConnection {
   public async registerDevice() {
     log('Device not registered. Registering ...');
     const deviceAuthorizationRequestResponse: Response = await this.createDeviceAuthorization({
-      url: this.deviceUrl,
+      url: KEYCLOAK_DEVICE_AUTH_URL,
       body: (() => {
         const params = new URLSearchParams();
         params.append('client_id', 'deadlock-desktop');
diff --git a/deadlock-plugins/deadlock-extension/src/core/mission/missionDevContainer.ts b/deadlock-plugins/deadlock-extension/src/core/mission/missionDevContainer.ts
index 0dddfb60b0b3e96a7d31cf43ac2eeab878a58280..edfbe815bd98fc8cfa9530a9fa359d3e751aca67 100644
--- a/deadlock-plugins/deadlock-extension/src/core/mission/missionDevContainer.ts
+++ b/deadlock-plugins/deadlock-extension/src/core/mission/missionDevContainer.ts
@@ -1,15 +1,16 @@
 import { missionWorkdir, userSshKeyFolderPath } from '../config';
 import { Base, DockerfileSpecific, LifecycleScripts, VSCodespecific } from './model/devContainer';
-import { mkdir, writeFile } from 'fs/promises';
-import { GiteaPublicProperties } from '../../model/giteaPublicProperties.model';
+import { writeFile } from 'fs/promises';
 import { commands, Uri, window } from 'vscode';
 import { existsSync, copyFileSync } from 'fs';
 import { join } from 'path';
 
-import assert = require('assert');
-import UserMission, { User } from './model/userMission';
+import UserMission from './model/userMission';
 import { REGISTRY_MISSION_URL } from '../../config';
 import { getReviewedStudentWorkdirPath } from '../utils/mission.utils';
+import { homedir } from 'os';
+import { extensionError } from '../../recorder/utils/log';
+import { createDirectories } from '../../recorder/utils/workdir';
 
 const remoteUserHomeDir = '/home/deadlock';
 const remoteMissionDir = `${remoteUserHomeDir}/mission/`;
@@ -30,31 +31,27 @@ export class MissionDevContainer {
 
   private readonly dirs: {
     missionWorkdir: string;
-    config: string;
     devcontainer: string;
     mounted: string;
     solution: string;
   };
 
   constructor(
-    private readonly user: User,
-    private readonly currentUser: User,
     private readonly missionId: string,
     private readonly missionVersion: string,
-    private readonly giteaProperties: GiteaPublicProperties,
+    private readonly revieweeId?: string,
   ) {
     let prefix: string;
-    if (this.isReviewingStudent()) {
-      prefix = getReviewedStudentWorkdirPath(this.user.id);
+    if (revieweeId) {
+      prefix = getReviewedStudentWorkdirPath(revieweeId);
     } else {
       prefix = `${missionWorkdir}`;
     }
     this.dirs = {
-      missionWorkdir: `${prefix}/${this.missionId}`,
-      config: `${prefix}/${this.missionId}/.config`,
-      devcontainer: `${prefix}/${this.missionId}/.devcontainer`,
-      mounted: `${prefix}/${this.missionId}/mounted`,
-      solution: `${prefix}/${this.missionId}/.solution`,
+      missionWorkdir: `${prefix}/${missionId}`,
+      devcontainer: `${prefix}/${missionId}/.devcontainer`,
+      mounted: `${prefix}/${missionId}/mounted`,
+      solution: `${prefix}/${missionId}/.solution`,
     };
     if (process.env.DL_MOUNT_EXTENSION === 'true') {
       this.extentionPath = '/injected-extension/extension.vsix';
@@ -67,7 +64,6 @@ export class MissionDevContainer {
     if (!this.isInit) {
       await this.init();
     }
-    assert(existsSync(this.dirs.missionWorkdir));
     await commands.executeCommand('remote-containers.openFolder', Uri.file(this.dirs.missionWorkdir));
   }
 
@@ -77,7 +73,7 @@ export class MissionDevContainer {
     }
     this.isInit = true;
     try {
-      await this.createDirectories(...Object.values(this.dirs));
+      await createDirectories(...Object.values(this.dirs));
       await this.createDevContainerFile();
       await this.createUserChallengeJsonFile();
     } catch (e) {
@@ -86,40 +82,19 @@ export class MissionDevContainer {
     }
   }
 
-  private isReviewingStudent() {
-    return this.currentUser.id !== this.user.id;
-  }
-
   private async createUserChallengeJsonFile() {
-    return writeFile(
-      `${this.dirs.config}/user-challenge.json`,
-      (() => {
-        const username = this.user.id.split('-').join('');
-        const userChallengeJson: UserMission = {
-          giteaHost: this.giteaProperties.sshHost,
-          userId: this.user.id,
-          giteaSshPort: this.giteaProperties.sshPort,
-          username,
-          email: `${username}@deadlock.io`,
-          missionId: this.missionId,
-          missionVersion: this.missionVersion,
-          remoteGitUsername: username,
-          currentUserDetails: this.currentUser.details,
-          currentUserId: this.currentUser.id,
-          remoteUserDetails: this.user.details,
-        };
-        return JSON.stringify(userChallengeJson, null, 2);
-      })(),
-    );
+    try {
+      await UserMission.writeFile(this.missionId, this.missionVersion, this.revieweeId);
+    } catch (e) {
+      extensionError(e);
+      window.showErrorMessage(`Une erreur est survenue lors de la création du fichier userChallenge.json`);
+    }
   }
 
   private addInMountRCs(tempFolder: string, ...rcs: string[]): void {
-    if (process.env.HOME === undefined) {
-      throw new Error('HOME environment variable is not defined');
-    }
     for (const rc of rcs) {
       if (existsSync(rc)) {
-        const rcPath = join(process.env.HOME, rc);
+        const rcPath = join(homedir(), rc);
         const tempRC = join(tempFolder, rc);
         const mountRC = join(remoteUserHomeDir, rc);
         copyFileSync(rcPath, tempRC);
@@ -132,14 +107,17 @@ export class MissionDevContainer {
     this.mounts.splice(0, this.mounts.length);
     this.mounts.push(
       `source=${userSshKeyFolderPath},target=/tmp/.ssh,type=bind,consistency=cached,readonly`,
-      `source=${this.dirs.config},target=/home/config/,type=bind,consistency=cached,readonly`,
+      `source=${UserMission.getMissionUserFolder(
+        this.missionId,
+        this.revieweeId,
+      )},target=/home/config/,type=bind,consistency=cached,readonly`,
       'source=/etc/hosts,target=/etc/hosts,type=bind,consistency=cached,readonly',
     );
     if (process.env.DL_MOUNT_EXTENSION === 'true') {
       this.mounts.push(`source=${process.env.EXTENSION_PATH},target=${this.extentionPath},type=bind`);
     }
     this.addInMountRCs(this.dirs.missionWorkdir, '.bashrc', '.zshrc');
-    if (this.isReviewingStudent()) {
+    if (this.revieweeId) {
       this.mounts.push(`source=${this.dirs.solution},target=${remoteMissionDir}/solution,type=bind`);
     }
   }
@@ -175,8 +153,4 @@ export class MissionDevContainer {
       })(),
     );
   }
-
-  private createDirectories(...directoryPaths: string[]) {
-    return Promise.all(directoryPaths.map((directoryPath) => mkdir(directoryPath, { recursive: true })));
-  }
 }
diff --git a/deadlock-plugins/deadlock-extension/src/core/mission/model/userMission.ts b/deadlock-plugins/deadlock-extension/src/core/mission/model/userMission.ts
index 063223991ec168e14fe2feb0a44130cead1d8683..95676b0972a3fe69774190b7e30d25c6ee892775 100644
--- a/deadlock-plugins/deadlock-extension/src/core/mission/model/userMission.ts
+++ b/deadlock-plugins/deadlock-extension/src/core/mission/model/userMission.ts
@@ -1,18 +1,82 @@
-interface UserMission {
-  giteaHost: string;
-  giteaSshPort: number;
-  userId: string;
-  username: string;
-  currentUserId: string;
-  email: string;
+import { readFileSync } from 'fs';
+import { writeFile } from 'fs/promises';
+import { join } from 'path';
+import { createDirectories } from '../../../recorder/utils/workdir';
+import ApiService from '../../api.service';
+import { missionWorkdir, USER_MISSION_PATH } from '../../config';
+import { getReviewedStudentWorkdirPath } from '../../utils/mission.utils';
+
+interface UserMissionModel {
   missionId: string;
   missionVersion: string;
-  remoteGitUsername: string;
-  currentUserDetails: UserDetails;
-  remoteUserDetails: UserDetails;
+  reviewee?: User;
 }
 
-export default UserMission;
+export default class UserMission implements UserMissionModel {
+  private static _instance: UserMission;
+
+  private constructor(userMission: UserMissionModel) {
+    this.missionId = userMission.missionId;
+    this.missionVersion = userMission.missionVersion;
+    this.reviewee = userMission.reviewee;
+    UserMission._instance = this;
+  }
+
+  public static getInstance(): UserMission {
+    if (!UserMission._instance) {
+      return (this._instance = new UserMission(JSON.parse(readFileSync(USER_MISSION_PATH, 'utf8'))));
+    }
+    return UserMission._instance;
+  }
+
+  private get apiService(): ApiService {
+    return ApiService.getInstance();
+  }
+
+  public async getGiteaUser(): Promise<User & { username: string }> {
+    const giteaUser: User & { username?: string } = this.reviewee ?? (await this.apiService.getCurrentUser());
+    return { ...giteaUser, username: giteaUser.id.split('-').join('') };
+  }
+
+  public async getEmail(): Promise<string> {
+    return `${(await this.getGiteaUser()).username}@deadlock.io`;
+  }
+
+  public readonly missionId: string;
+  public readonly missionVersion: string;
+  public readonly reviewee?: User;
+
+  public static getMissionUserFolder(missionId: string, revieweeId?: string): string {
+    return join(revieweeId ? getReviewedStudentWorkdirPath(revieweeId) : missionWorkdir, missionId, '.config');
+  }
+
+  public static async writeFile(missionId: string, missionVersion: string, revieweeId?: string): Promise<void> {
+    const workdir = this.getMissionUserFolder(missionId, revieweeId);
+    await createDirectories(workdir);
+    const user = await ApiService.getInstance().getCurrentUser();
+    const username = (revieweeId ?? user.id).split('-').join('');
+    const path = join(workdir, 'user-challenge.json');
+    await writeFile(
+      path,
+      JSON.stringify(
+        {
+          username,
+          email: `${username}@deadlock.io`,
+          missionId,
+          missionVersion,
+          remoteGitUsername: username,
+          reviewee: revieweeId ? await ApiService.getInstance().getUser(revieweeId) : undefined,
+        } as UserMissionModel,
+        null,
+        2,
+      ),
+    );
+  }
+
+  public isReviewing(): boolean {
+    return !!this.reviewee;
+  }
+}
 
 export interface UserDetails {
   id: string;
@@ -31,10 +95,3 @@ export interface User {
   id: string;
   details: UserDetails;
 }
-
-export function isReviewingStudent(userMission: UserMission) {
-  return (
-    userMission.remoteGitUsername !== userMission.username &&
-    (userMission.currentUserDetails.roles.has('PROFESSOR') || userMission.currentUserDetails.roles.has('ADMIN'))
-  );
-}
diff --git a/deadlock-plugins/deadlock-extension/src/core/userConfig.ts b/deadlock-plugins/deadlock-extension/src/core/userConfig.ts
deleted file mode 100644
index 30f705760515891e7b104daf7ae1ae4290ab2701..0000000000000000000000000000000000000000
--- a/deadlock-plugins/deadlock-extension/src/core/userConfig.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * Example:
- * {
- * "paths": {
- *  "9090":"HXW3fnKwUULrfKS1-cdb",
- *  "3000":"HXW3fnKwUULrfKS1-web",
- *  "8080":"HXW3fnKwUULrfKS1-angular"
- *  },
- * "host":"dev.deadlock.io",
- * "token":"e75da487-9576-4427-be2d-8da4059adc7d",
- * "giteaHost":"deadlock.minikube",
- * "giteaSshPort":32000,
- * "username":"slayug",
- * "missionId":"code_persist_cdb_crud"
- * }
- */
-import { Uri, workspace } from 'vscode';
-import { recorderError as error } from '../recorder/utils/log';
-import { USER_CHALLENGE_PATH } from './config';
-import UserMission from './mission/model/userMission';
-
-export default class UserConfig {
-  private _userConfigJson?: UserMission;
-
-  async init() {
-    try {
-      const textDocument = await workspace.openTextDocument(Uri.parse(USER_CHALLENGE_PATH));
-      this._userConfigJson = JSON.parse(textDocument.getText());
-    } catch (e) {
-      error(`Error loading user config: ${e}`);
-      throw e;
-    }
-  }
-
-  get userConfigJson(): UserMission {
-    return this._userConfigJson!;
-  }
-}
diff --git a/deadlock-plugins/deadlock-extension/src/core/utils/mission.utils.ts b/deadlock-plugins/deadlock-extension/src/core/utils/mission.utils.ts
index edb8400ddb479d80c011c594a022b6de4b9020ce..8238c3a78c585139b4badc5f00fbcb2132b9c52c 100644
--- a/deadlock-plugins/deadlock-extension/src/core/utils/mission.utils.ts
+++ b/deadlock-plugins/deadlock-extension/src/core/utils/mission.utils.ts
@@ -1,6 +1,6 @@
 import { PathLike, readFileSync } from 'fs';
 import { join } from 'path';
-import { missionWorkdir, USER_CHALLENGE_PATH } from '../config';
+import { missionWorkdir, USER_MISSION_PATH } from '../config';
 import UserMission from '../mission/model/userMission';
 import isDocker from './isdocker';
 
@@ -11,7 +11,7 @@ export function getReviewedStudentWorkdirPath(userId: string): string {
 export function getUserChallenge(userId: string, missionid: string, isReviewing = false): UserMission {
   let path: number | PathLike;
   if (isDocker()) {
-    path = USER_CHALLENGE_PATH;
+    path = USER_MISSION_PATH;
   } else if (isReviewing) {
     path = join(getReviewedStudentWorkdirPath(userId), missionid, '.config', 'userChallenge.json');
   } else {
diff --git a/deadlock-plugins/deadlock-extension/src/extension.ts b/deadlock-plugins/deadlock-extension/src/extension.ts
index 4a2b288c90a43cf0846aaf7cf5870665972a917b..29abd15f0646e09b24554bea29ee9ba38003652d 100644
--- a/deadlock-plugins/deadlock-extension/src/extension.ts
+++ b/deadlock-plugins/deadlock-extension/src/extension.ts
@@ -1,28 +1,12 @@
 import { window, ExtensionContext, workspace, commands } from 'vscode';
 import Controller from './core/controller';
-import UserConfig from './core/userConfig';
 import isDocker from './core/utils/isdocker';
-import Recorder from './recorder/recorder';
+import Recorder, { runTimer } from './recorder/recorder';
 import { extensionError as error } from './recorder/utils/log';
-import { DepNodeProvider } from './theia/deadlockPanel';
+import { DepNodeProvider } from './view/deadlockPanel';
 import { CommandTreeProvider } from './view/CommandTree';
 import StartedMissionsView from './view/startedMissionsView';
 
-export const userConfig = new UserConfig();
-
-export async function runTimer(userId: string, missionId: string, context: ExtensionContext) {
-  const apiService = Controller.getInstance(context).apiService;
-  try {
-    await apiService.startUpdateWorkTime(userId, missionId);
-    setInterval(async () => {
-      await apiService.pingUpdateWorkTime(userId, missionId);
-    }, 60000); // 1 minute
-  } catch (e) {
-    window.showErrorMessage(`Erreur lors de l'enregistrement du temps de travail`);
-    error(JSON.stringify(e));
-  }
-}
-
 export async function activate(context: ExtensionContext) {
   window.showInformationMessage('Bienvenue sur Deadlock!');
   Controller.getInstance(context);
@@ -39,12 +23,6 @@ export async function activate(context: ExtensionContext) {
   } else {
     commands.executeCommand('setContext', 'deadlock.inContainer', false);
   }
-  try {
-    await userConfig.init();
-  } catch (e) {
-    error(JSON.stringify(e));
-    error('Cannot init userConfig');
-  }
   if (isDocker()) {
     try {
       Recorder.instance.run();
@@ -53,6 +31,6 @@ export async function activate(context: ExtensionContext) {
       error(JSON.stringify(e));
       window.showErrorMessage("Le recorder n'a pas pu être lancé");
     }
-    runTimer(userConfig.userConfigJson.currentUserId, userConfig.userConfigJson.missionId, context);
+    runTimer();
   }
 }
diff --git a/deadlock-plugins/deadlock-extension/src/recorder/recorder.ts b/deadlock-plugins/deadlock-extension/src/recorder/recorder.ts
index 192ff3235d9ae4fdcc8b2aaf6930509c17d928d1..a1fe2de133dc9ab5a3b25543a3d09551e465ce78 100644
--- a/deadlock-plugins/deadlock-extension/src/recorder/recorder.ts
+++ b/deadlock-plugins/deadlock-extension/src/recorder/recorder.ts
@@ -1,19 +1,22 @@
-import { Branch } from '../core/gitMission';
 import { ENABLE_AUTOMATIC_SAVE } from '../config';
 import GitMission from '../core/gitMission';
-import UserConfigNode from './userConfigNode';
-import { PROJECT_DEADLOCK_DESKTOP_PATH, PROJECT_SRC_PATH } from '../core/config';
+import { MISSION_PATH_IC, GITEA_PATH_IC } from '../core/config';
 import { recorderError as error } from './utils/log';
-import UserConfig from '../core/userConfig';
 import AutomaticSave from './services/automatic-save';
 import { clearFilesExceptGit, copyProjectSources, renameTempToUserGitFiles } from './utils/workdir';
 import aquirePermissions from './utils/permission';
-import { isReviewingStudent } from '../core/mission/model/userMission';
+import UserMission from '../core/mission/model/userMission';
+import ApiService from '../core/api.service';
+import { window } from 'vscode';
+
 export default class Recorder {
   private _gitMission?: GitMission;
-  private userConfig?: UserConfigNode;
   private static _instance?: Recorder;
 
+  private get userMission(): UserMission {
+    return UserMission.getInstance();
+  }
+
   private constructor() {
     Recorder._instance = this;
   }
@@ -26,26 +29,18 @@ export default class Recorder {
   }
 
   public get gitMission(): GitMission {
-    // TODO refactor remove !
     return this._gitMission!;
   }
 
-  async setupProject(userConfig: UserConfig, gitMission?: GitMission) {
-    if (!isReviewingStudent(userConfig.userConfigJson)) {
-      await copyProjectSources(PROJECT_SRC_PATH, PROJECT_DEADLOCK_DESKTOP_PATH, [
-        '.git/',
-        `user-git-${userConfig.userConfigJson.username}`,
-      ]);
-
-      if (gitMission) {
-        renameTempToUserGitFiles(PROJECT_DEADLOCK_DESKTOP_PATH, gitMission.author);
-      } else {
-        error('Cannot start command recorder, gitMission not found');
-      }
-    } else {
-      await copyProjectSources(PROJECT_SRC_PATH, PROJECT_DEADLOCK_DESKTOP_PATH, [
-        `user-git-${userConfig.userConfigJson.username}`,
-      ]);
+  async setupProject(gitMission: GitMission) {
+    await copyProjectSources(
+      GITEA_PATH_IC,
+      MISSION_PATH_IC,
+      '.git',
+      `user-git-${(await this.userMission.getGiteaUser()).username}`,
+    );
+    if (!this.userMission.isReviewing()) {
+      renameTempToUserGitFiles(MISSION_PATH_IC, await gitMission.getAuthor());
     }
   }
 
@@ -53,30 +48,27 @@ export default class Recorder {
     const isRemoteRepoExist = await gitMission.isRemoteRepoExist();
     if (isRemoteRepoExist) {
       // rm all except git directory pull remote code and setup
-      await clearFilesExceptGit(PROJECT_SRC_PATH);
+      await clearFilesExceptGit(GITEA_PATH_IC);
 
       await gitMission.fetch();
-      await gitMission.checkout(Branch.MASTER);
-      await gitMission.checkout(Branch.LIVE);
+      await gitMission.checkout('master');
+      await gitMission.checkout('live');
     } else {
       await gitMission.commit('initial commit', ['--allow-empty']);
-      await gitMission.createRemoteBranch(Branch.DEFAULT);
-      await gitMission.createBranch(Branch.LIVE);
+      await gitMission.createRemoteBranch();
+      await gitMission.createBranch('live');
     }
   }
 
   async run() {
-    this.userConfig = new UserConfigNode();
-
     try {
       await aquirePermissions();
       // TODO refactor remove this
-      await this.userConfig.init();
-      this._gitMission = await new GitMission(this.userConfig).init();
+      this._gitMission = await new GitMission().init();
       await this.setupFromRemoteRepo(this._gitMission);
-      await this.setupProject(this.userConfig, this._gitMission);
+      await this.setupProject(this._gitMission);
       try {
-        if (ENABLE_AUTOMATIC_SAVE) new AutomaticSave(PROJECT_DEADLOCK_DESKTOP_PATH, this._gitMission);
+        if (ENABLE_AUTOMATIC_SAVE) new AutomaticSave(MISSION_PATH_IC, this._gitMission);
       } catch (e) {
         error('Error while setup automatic save');
         error(e);
@@ -87,3 +79,16 @@ export default class Recorder {
     }
   }
 }
+
+export async function runTimer() {
+  const apiService = ApiService.getInstance();
+  try {
+    await apiService.startUpdateWorkTime();
+    setInterval(async () => {
+      await apiService.pingUpdateWorkTime();
+    }, 60000); // 1 minute
+  } catch (e) {
+    window.showErrorMessage(`Erreur lors de l'enregistrement du temps de travail`);
+    error(JSON.stringify(e));
+  }
+}
diff --git a/deadlock-plugins/deadlock-extension/src/recorder/userConfigNode.ts b/deadlock-plugins/deadlock-extension/src/recorder/userConfigNode.ts
deleted file mode 100644
index 025deb64fa4404ca13b7c0924a24a21fc38dcdb9..0000000000000000000000000000000000000000
--- a/deadlock-plugins/deadlock-extension/src/recorder/userConfigNode.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import UserConfig from '../core/userConfig';
-import { USER_CHALLENGE_PATH } from '../core/config';
-import { readFileSync } from 'fs';
-
-export default class UserConfigNode extends UserConfig {
-  async loadText(): Promise<string> {
-    const text = readFileSync(USER_CHALLENGE_PATH, 'utf8');
-
-    return Promise.resolve(text);
-  }
-}
diff --git a/deadlock-plugins/deadlock-extension/src/recorder/utils/gitea.ts b/deadlock-plugins/deadlock-extension/src/recorder/utils/gitea.ts
index 0a600f631ffa712caea3a09281c7fcbeeb7236cd..c0b98092c7a415dcba2e5af4bdd12da0fd87a3aa 100644
--- a/deadlock-plugins/deadlock-extension/src/recorder/utils/gitea.ts
+++ b/deadlock-plugins/deadlock-extension/src/recorder/utils/gitea.ts
@@ -1,6 +1,5 @@
-import { Branch } from '../../core/gitMission';
 import GitMission from '../../core/gitMission';
-import { DEADLOCK_WORKDIR_PATH, PROJECT_DEADLOCK_DESKTOP_PATH, PROJECT_SRC_PATH } from '../../core/config';
+import { DEADLOCK_WORKDIR_PATH, MISSION_PATH_IC, GITEA_PATH_IC } from '../../core/config';
 import { format } from 'date-fns';
 import { execSync } from 'child_process';
 import { existsSync, promises } from 'fs';
@@ -31,15 +30,13 @@ export async function commitAndPushOnQueue(gitMission: GitMission, from: 'Run' |
 
 async function commitAndPushCode(gitMission: GitMission) {
   try {
-    await gitMission.checkout(Branch.LIVE);
-    await clearFilesExceptGit(PROJECT_SRC_PATH);
+    await gitMission.checkout('live');
+    await clearFilesExceptGit(GITEA_PATH_IC);
 
-    copyGitUserFiles(PROJECT_DEADLOCK_DESKTOP_PATH, PROJECT_SRC_PATH, gitMission.author);
-    execSync(
-      `rsync -r --exclude .git --exclude node_modules --exclude target ${PROJECT_DEADLOCK_DESKTOP_PATH}/* ${PROJECT_SRC_PATH}`,
-    );
+    copyGitUserFiles(MISSION_PATH_IC, GITEA_PATH_IC, await gitMission.getAuthor());
+    execSync(`rsync -r --exclude .git --exclude node_modules --exclude target ${MISSION_PATH_IC}/* ${GITEA_PATH_IC}`);
     if (existsSync(join(DEADLOCK_WORKDIR_PATH, '.gitignore'))) {
-      await copyFile(join(DEADLOCK_WORKDIR_PATH, '.gitignore'), join(PROJECT_SRC_PATH, '.gitignore'));
+      await copyFile(join(DEADLOCK_WORKDIR_PATH, '.gitignore'), join(GITEA_PATH_IC, '.gitignore'));
     }
 
     const currentDate = format(new Date(), "HH'H'mm'_'dd/LL/y");
@@ -65,12 +62,12 @@ async function mergeMaster(gitMission: GitMission) {
 
     const currentDate = format(new Date(), "HH'H'mm'_'dd/LL/y");
 
-    await gitMission.checkout(Branch.DEFAULT);
-    await gitMission.merge(['--squash', '-X', 'theirs', Branch.LIVE]);
+    await gitMission.checkout();
+    await gitMission.merge(['--squash', '-X', 'theirs', 'live']);
     await gitMission.commit(currentDate);
     await gitMission.push();
     log('Merge to master done');
-    await gitMission.checkout(Branch.LIVE);
+    await gitMission.checkout('live');
   } catch (e) {
     if (e instanceof GitError) {
       error(`[${e.task?.commands}] cannot commitAndPush`);
diff --git a/deadlock-plugins/deadlock-extension/src/recorder/utils/permission.ts b/deadlock-plugins/deadlock-extension/src/recorder/utils/permission.ts
index 2d507d5af6e93ea25dc6d86a2be3e6d56404f9fc..6ad541f556114e89549dda294079b4c6dbaa7dbd 100644
--- a/deadlock-plugins/deadlock-extension/src/recorder/utils/permission.ts
+++ b/deadlock-plugins/deadlock-extension/src/recorder/utils/permission.ts
@@ -1,10 +1,10 @@
 import { exec as execCallback } from 'child_process';
 import { userInfo } from 'os';
 import { promisify } from 'util';
-import { PROJECT_SRC_PATH } from '../../core/config';
+import { GITEA_PATH_IC } from '../../core/config';
 
 const exec = promisify(execCallback);
 
 export default async function aquirePermissions() {
-  await exec(`sudo chown -R ${userInfo().username} ${PROJECT_SRC_PATH}`);
+  await exec(`sudo chown -R ${userInfo().username} ${GITEA_PATH_IC}`);
 }
diff --git a/deadlock-plugins/deadlock-extension/src/recorder/utils/workdir.ts b/deadlock-plugins/deadlock-extension/src/recorder/utils/workdir.ts
index c446bebaa442c49776c19486b48208ed9fddf1f1..acb35be4f28d154d6ed6db0078c3f4271c70ad80 100644
--- a/deadlock-plugins/deadlock-extension/src/recorder/utils/workdir.ts
+++ b/deadlock-plugins/deadlock-extension/src/recorder/utils/workdir.ts
@@ -8,15 +8,9 @@ import { mkdir, rm } from 'fs/promises';
 const exec = promisify(execCallback);
 const PREFIX = '[DEADLOCK-RECORDER]';
 
-export async function copyProjectSources(
-  srcPath: string,
-  userMissionWorkdirPath: string,
-  excludes: Array<string> = [],
-) {
+export async function copyProjectSources(src: string, target: string, ...excludes: Array<string>) {
   const excludeCmd = excludes.map((current) => `--exclude ${current}`).join(' ');
-  return await exec(
-    `sudo rsync -a ${srcPath}/ ${userMissionWorkdirPath} ${excludeCmd} && sudo chown -R deadlock:deadlock /home/deadlock`,
-  );
+  return await exec(`sudo rsync -a ${src}/ ${target} ${excludeCmd} && sudo chown -R deadlock:deadlock /home/deadlock`);
 }
 
 export async function clearFilesExceptGit(path: string) {
@@ -57,11 +51,11 @@ function copyFolderIfExistsSync(srcPath: PathLike, destPath: PathLike) {
  * Rename temporary git files back to actual git files.
  *
  * @param path Path of the folder containing user's temporary git project files.
- * @param userId Identifier used to create the temporary files name
+ * @param username Identifier used to create the temporary files name
  */
-export function renameTempToUserGitFiles(path: string, userId: string) {
-  renameIfExistsSync(join(path, `user-git-${userId}`), join(path, '.git'));
-  renameIfExistsSync(join(path, `user-gitignore-${userId}`), join(path, '.gitignore'));
+export function renameTempToUserGitFiles(path: string, username: string) {
+  renameIfExistsSync(join(path, `user-git-${username}`), join(path, '.git'));
+  renameIfExistsSync(join(path, `user-gitignore-${username}`), join(path, '.gitignore'));
 }
 
 /**
@@ -71,11 +65,11 @@ export function renameTempToUserGitFiles(path: string, userId: string) {
  *
  * @param srcPath Path of the folder containing user's git project files to be saved.
  * @param destPath Path where the user's git project files should be pasted.
- * @param userId Identifier used to create the temporary files name
+ * @param username Identifier used to create the temporary files name
  */
-export function copyGitUserFiles(srcPath: string, destPath: string, userId: string) {
-  copyFolderIfExistsSync(join(srcPath, '.git'), join(destPath, `user-git-${userId}`));
-  copyFileIfExistsSync(join(srcPath, '.gitignore'), join(destPath, `user-gitignore-${userId}`));
+export function copyGitUserFiles(srcPath: string, destPath: string, username: string) {
+  copyFolderIfExistsSync(join(srcPath, '.git'), join(destPath, `user-git-${username}`));
+  copyFileIfExistsSync(join(srcPath, '.gitignore'), join(destPath, `user-gitignore-${username}`));
 }
 
 export async function removeFilesOrDirectories(...paths: string[]) {
@@ -90,3 +84,7 @@ export async function emptyDirectories(...directoryPaths: string[]) {
     await mkdir(directoryPath);
   }
 }
+
+export async function createDirectories(...directoryPaths: string[]) {
+  return Promise.all(directoryPaths.map((directoryPath) => mkdir(directoryPath, { recursive: true })));
+}
diff --git a/deadlock-plugins/deadlock-extension/src/theia/command.ts b/deadlock-plugins/deadlock-extension/src/theia/command.ts
deleted file mode 100644
index f785eb10101000de8879e5fd68626b5c6a74d388..0000000000000000000000000000000000000000
--- a/deadlock-plugins/deadlock-extension/src/theia/command.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { Command as VscodeComand } from 'vscode';
-
-export class VsCommand {
-  constructor(private _title: string, private command: string) {}
-
-  get title() {
-    return this._title;
-  }
-
-  get cmd() {
-    return this.command;
-  }
-
-  asVsCodeCommand(): VscodeComand {
-    return { title: this.title, command: this.cmd };
-  }
-}
-
-export const openBriefingCommand = new VsCommand('Open Briefing', 'deadlock.openBriefing');
-export const openQuickSetupCommand = new VsCommand('Open Deadlock quick setup page', 'deadlock.openQuickSetup');
diff --git a/deadlock-plugins/deadlock-extension/src/view/CommandTree.ts b/deadlock-plugins/deadlock-extension/src/view/CommandTree.ts
index 9edb00cea6ccc2aebc732af93831eaad24d17702..78640e7889efbfe3db1e54da7a603bb6321fa473 100644
--- a/deadlock-plugins/deadlock-extension/src/view/CommandTree.ts
+++ b/deadlock-plugins/deadlock-extension/src/view/CommandTree.ts
@@ -50,11 +50,13 @@ class CommandItem extends TreeItem {
     };
     commands.registerCommand(missionCommand.name, () => {
       if (missionCommand.type === 'submit') {
-        window.showInformationMessage('Êtes-vous sûr de soumettre votre solution ?', 'Oui', 'Non').then((answer) => {
-          if (answer === 'Oui') {
-            this.apply();
-          }
-        });
+        window
+          .showInformationMessage('Êtes-vous sûr de soumettre votre solution ?', { modal: true }, 'Oui', 'Non')
+          .then((answer) => {
+            if (answer === 'Oui') {
+              this.apply();
+            }
+          });
       } else {
         this.apply();
       }
diff --git a/deadlock-plugins/deadlock-extension/src/view/briefingView.ts b/deadlock-plugins/deadlock-extension/src/view/briefingView.ts
index 9d8b40c2b454d4bf0749b91da81979c0795ec814..ae6dfaf5a7f4b25dd89388998e0831c778a18274 100644
--- a/deadlock-plugins/deadlock-extension/src/view/briefingView.ts
+++ b/deadlock-plugins/deadlock-extension/src/view/briefingView.ts
@@ -3,11 +3,11 @@ import { marked } from 'marked';
 import { join } from 'path';
 import { setInterval } from 'timers';
 import { Uri, workspace } from 'vscode';
-import { BRIEFING_FILE_NAME, DOCS_PATH } from '../core/config';
-import { isReviewingStudent } from '../core/mission/model/userMission';
+import ApiService from '../core/api.service';
+import { BRIEFING_FILE_NAME, DOCS_PATH_IC } from '../core/config';
+import { openBriefingCommand } from '../core/controller';
+import UserMission from '../core/mission/model/userMission';
 import isDocker from '../core/utils/isdocker';
-import { userConfig } from '../extension';
-import { openBriefingCommand } from '../theia/command';
 import { WebviewBase } from './webviewBase';
 
 export const briefingId = 'brefingView';
@@ -23,7 +23,7 @@ export default class BriefingView extends WebviewBase {
   }
 
   toBase64(file: string) {
-    const result = readFileSync(join(DOCS_PATH, file), {
+    const result = readFileSync(join(DOCS_PATH_IC, file), {
       encoding: 'base64',
     });
     return result;
@@ -47,7 +47,7 @@ export default class BriefingView extends WebviewBase {
         this.loadingBriefing = true;
         clearInterval(intervalId);
 
-        workspace.openTextDocument(Uri.parse(join(DOCS_PATH, BRIEFING_FILE_NAME))).then(
+        workspace.openTextDocument(Uri.parse(join(DOCS_PATH_IC, BRIEFING_FILE_NAME))).then(
           (document) => {
             try {
               this.briefingContent = this.setupImages(document.getText());
@@ -66,13 +66,17 @@ export default class BriefingView extends WebviewBase {
     }, 500);
   }
 
-  render() {
+  async render() {
     let output = '';
 
-    if (isReviewingStudent(userConfig.userConfigJson)) {
+    const missionUser = UserMission.getInstance();
+
+    if (missionUser.isReviewing()) {
+      const user = await ApiService.getInstance().getCurrentUser();
+      const giteaUser = await missionUser.getGiteaUser();
       output += `
         <h2>Professeur</h2>
-        Bonjour ${userConfig.userConfigJson.currentUserDetails.lastName} ${userConfig.userConfigJson.currentUserDetails.firstName} vous êtes actuellement entrain de relire le code de <b>${userConfig.userConfigJson.currentUserDetails.lastName} ${userConfig.userConfigJson.currentUserDetails.firstName}</b>.<br />
+        Bonjour <b>${user.details.lastName} ${user.details.firstName}</b> vous êtes actuellement entrain de relire le code de <b>${giteaUser.details.lastName} ${giteaUser.details.firstName}</b>.<br />
         Vous pouvez consulter chaque exécution de son code dans l'onglet à gauche de GitLens. Chaque commit sur <b>master</b> représente une exécution.
         <br />
       `;
diff --git a/deadlock-plugins/deadlock-extension/src/theia/deadlockPanel.ts b/deadlock-plugins/deadlock-extension/src/view/deadlockPanel.ts
similarity index 88%
rename from deadlock-plugins/deadlock-extension/src/theia/deadlockPanel.ts
rename to deadlock-plugins/deadlock-extension/src/view/deadlockPanel.ts
index f8a48cb423f5f66be71746cf96d8a2895190aef4..d41de08c45ec1750239b072c45f3587de90266e2 100644
--- a/deadlock-plugins/deadlock-extension/src/theia/deadlockPanel.ts
+++ b/deadlock-plugins/deadlock-extension/src/view/deadlockPanel.ts
@@ -1,6 +1,6 @@
 import { join } from 'path';
 import { Command, Event, EventEmitter, TreeDataProvider, TreeItem, TreeItemCollapsibleState } from 'vscode';
-import { openBriefingCommand } from './command';
+import { openBriefingCommand } from '../core/controller';
 
 const documentationLabel = 'Documentation';
 
@@ -25,9 +25,7 @@ export class DepNodeProvider implements TreeDataProvider<Action> {
     if (!element) {
       return Promise.resolve(this.root());
     } else if (element.label === documentationLabel) {
-      return Promise.resolve([
-        new Action('Briefing', TreeItemCollapsibleState.None, 'document', openBriefingCommand.asVsCodeCommand()),
-      ]);
+      return Promise.resolve([new Action('Briefing', TreeItemCollapsibleState.None, 'document', openBriefingCommand)]);
     }
 
     return Promise.resolve([]);
diff --git a/deadlock-plugins/deadlock-extension/src/view/quickSetupView.ts b/deadlock-plugins/deadlock-extension/src/view/quickSetupView.ts
index 7610ca20533dafa02126fc298cddd22e84ad7a8a..0c3ec6a80c8760db1e4c03eca115fbbe5bc07c81 100644
--- a/deadlock-plugins/deadlock-extension/src/view/quickSetupView.ts
+++ b/deadlock-plugins/deadlock-extension/src/view/quickSetupView.ts
@@ -1,8 +1,8 @@
 import { commands, Uri } from 'vscode';
 import { authenticateCommand, disconnectCommand } from '../core/commandHandler';
+import { openQuickSetupCommand } from '../core/controller';
 import ExtensionStore from '../core/extensionStore';
 import { extensionLog as log } from '../recorder/utils/log';
-import { openQuickSetupCommand } from '../theia/command';
 import { WebviewBase } from './webviewBase';
 
 export const quickSetupId = 'quickSetup';
@@ -26,7 +26,7 @@ export default class QuickSetupView extends WebviewBase {
     }
   }
 
-  render(): string {
+  async render(): Promise<string> {
     return `
          <head>
             ${this.renderHeaderHtml()}
@@ -114,10 +114,10 @@ export default class QuickSetupView extends WebviewBase {
   onMessageReceive(message: any): void {
     switch (message.command) {
       case 'openAuthenticationPageAction':
-        commands.executeCommand(authenticateCommand.cmd);
+        commands.executeCommand(authenticateCommand.command);
         return;
       case 'disconnectUserAction':
-        commands.executeCommand(disconnectCommand.cmd);
+        commands.executeCommand(disconnectCommand.command);
         return;
     }
   }
diff --git a/deadlock-plugins/deadlock-extension/src/view/webviewBase.ts b/deadlock-plugins/deadlock-extension/src/view/webviewBase.ts
index ebfbe6836aba9e3d46ae7b7c6d2e0b62672846ae..a2a62417a14fafdf86c917acca48502ea06bd0e4 100644
--- a/deadlock-plugins/deadlock-extension/src/view/webviewBase.ts
+++ b/deadlock-plugins/deadlock-extension/src/view/webviewBase.ts
@@ -1,5 +1,6 @@
 'use strict';
 import {
+  Command,
   commands,
   Disposable,
   Uri,
@@ -9,7 +10,6 @@ import {
   WebviewPanelOnDidChangeViewStateEvent,
   window,
 } from 'vscode';
-import { VsCommand } from '../theia/command';
 
 const emptyCommands: Disposable[] = [
   {
@@ -28,8 +28,8 @@ export abstract class WebviewBase implements Disposable {
   private disposablePanel: Disposable | undefined;
   protected panel: WebviewPanel | undefined;
 
-  constructor(private id: string, private title: string, command: VsCommand, private readonly _column?: ViewColumn) {
-    this.disposable = Disposable.from(commands.registerCommand(command.cmd, this.onShowCommand, this));
+  constructor(private id: string, private title: string, command: Command, private readonly _column?: ViewColumn) {
+    this.disposable = Disposable.from(commands.registerCommand(command.command, this.onShowCommand, this));
     this.load();
   }
 
@@ -130,13 +130,13 @@ export abstract class WebviewBase implements Disposable {
   /**
    * Must return the content displayed within the webViewPanel
    */
-  abstract render(): string;
+  abstract render(): Promise<string>;
   /**
    * Method called at the end of first render
    */
   abstract load(): void;
 
   private async getHtml(): Promise<string> {
-    return this.render();
+    return await this.render();
   }
 }