diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4c06113b59fab532939026c1253305610dd6f728..da9d85a63776ef536cc6549f76c3551db2cda4bb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,7 +18,19 @@
 -->
 
 
-## 3.3.0 (???)
+## 3.4.0 (???)
+
+### ✨ Feature
+- Limit of 2 exercises by user
+
+### 🔨 Internal / Developers
+- **CLI**: Suffix package and binaries with version name
+
+### 🐛 Bugfix
+- **CLI CI/CD**: Fix deletion of packages on release
+
+
+## 3.3.0 (2023-01-18)
 
 ### ✨ Feature
 - Add a run command on assignment (to run the assignment as an exercise)
diff --git a/NodeApp/.gitlab-ci/01_functions.yml b/NodeApp/.gitlab-ci/01_functions.yml
index 08bddf31c6f3805135cc0916127343ea14a726bc..231424194f00183d07f31b1aec69137e3efbe791 100644
--- a/NodeApp/.gitlab-ci/01_functions.yml
+++ b/NodeApp/.gitlab-ci/01_functions.yml
@@ -12,6 +12,19 @@
                 BIN_NAME="dojo-test"
                 DOTENV_PROD_KEY=$DOTENV_TEST_KEY
             fi
+
+
+.get_version:
+    script:
+        - VERSION=$(jq -r .version $PROJECT_FOLDER/package.json)$([[ $IS_TEST == true ]] && echo $VERSION_TEST_SUFFIX || echo '' )$([[ $IS_DEV == true ]] && echo $VERSION_DEV_SUFFIX || echo '')
+
+
+# Require that the VERSION env var is set
+.get_version_dependent_vars:
+    script:
+        - BIN_NAME_BASE="${BIN_NAME}"
+        - BIN_NAME="${BIN_NAME_BASE}${VERSION}"
+
         - PKG_BIN_NAME_DEBIAN="${BIN_NAME}${PKG_EXTENSION_DEBIAN}"
         - PKG_BIN_NAME_MACOS="${BIN_NAME}${PKG_EXTENSION_MACOS}"
         - BIN_NAME_WINDOWS="${BIN_NAME}${BIN_EXTENSION_WINDOWS}"
@@ -31,11 +44,6 @@
         - PACKAGE_REGISTRY_URL="${GITLAB_API_PROJECT_URL}/packages/generic/${BIN_NAME}"
 
 
-.get_version:
-    script:
-        - VERSION=$(jq -r .version $PROJECT_FOLDER/package.json)$([[ $IS_TEST == true ]] && echo $VERSION_TEST_SUFFIX || echo '' )$([[ $IS_DEV == true ]] && echo $VERSION_DEV_SUFFIX || echo '')
-
-
 .get_last_stable_version:
     script:
         # Get all releases of the project
@@ -127,10 +135,10 @@
 .clean_packages:
     script:
         # Get all packages of the project
-        - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" "${GITLAB_API_PROJECT_URL}/packages" > gitlabPackages.json'
+        - 'curl --header "JOB-TOKEN: $CI_JOB_TOKEN" "${GITLAB_API_PROJECT_URL}/packages?sort=desc&package_version=${VERSION}" > gitlabPackages.json'
 
         # Filter and select packages to delete (based on version)
-        - packagesToDelete=`jq -r '.[] | select(.version=="'${VERSION}'") | ._links.delete_api_path' gitlabPackages.json`
+        - packagesToDelete=`jq -r '.[] | ._links.delete_api_path' gitlabPackages.json`
 
         # Delete packages by calling Gitlab API
         - >
diff --git a/NodeApp/.gitlab-ci/02_templates.yml b/NodeApp/.gitlab-ci/02_templates.yml
index 8bf24a6f5a203cdb1ea621d04d0091a785bbd960..41ca52ff2ee29ca7b5adc9f7483c279d35c21b81 100644
--- a/NodeApp/.gitlab-ci/02_templates.yml
+++ b/NodeApp/.gitlab-ci/02_templates.yml
@@ -12,16 +12,17 @@
 
         # Get vars
         - !reference [ .get_version, script ]
+        - !reference [ .get_version_dependent_vars, script ]
         - !reference [ .get_last_stable_version, script ]
 
         - cd $BIN_FOLDER_DEBIAN_PKG_AND_SIGN
-        - PKG_BUILD_FOLDER_NAME="${BIN_NAME}_${VERSION}_${ARCH}"
+        - PKG_BUILD_FOLDER_NAME="${BIN_NAME_BASE}_${VERSION}_${ARCH}"
 
 
         # Pkg tree creation
         - mkdir -p "${PKG_BUILD_FOLDER_NAME}/usr/local/bin/"
         ## Copy binary
-        - cp -R ${BIN_NAME} "${PKG_BUILD_FOLDER_NAME}/usr/local/bin/"
+        - cp -R ${BIN_NAME} "${PKG_BUILD_FOLDER_NAME}/usr/local/bin/${BIN_NAME_BASE}"
         ## Copy debian folder with package definition files
         - cp -R "${RESOURCES_FOLDER}/Debian/pkg/DEBIAN" "${PKG_BUILD_FOLDER_NAME}"
 
@@ -30,18 +31,18 @@
         ## control file
         - sed -i -r "s%\{\{VERSION\}\}%${VERSION}%g" control
         - sed -i -r "s%\{\{ARCH\}\}%${ARCH}%g" control
-        - sed -i -r "s%\{\{BIN_NAME\}\}%${BIN_NAME}%g" control
+        - sed -i -r "s%\{\{BIN_NAME\}\}%${BIN_NAME_BASE}%g" control
         ## changelog file
         - STABILITY=$([[ $IS_DEV == true ]] && echo 'unstable' || echo 'stable')
         - PRIORITY=$([[ ${VERSION%.*} == ${LAST_STABLE_VERSION%.*} ]] && echo 'medium' || echo 'high')
         - sed -i -r "s%\{\{VERSION\}\}%${VERSION}%g" changelog
-        - sed -i -r "s%\{\{BIN_NAME\}\}%${BIN_NAME}%g" changelog
+        - sed -i -r "s%\{\{BIN_NAME\}\}%${BIN_NAME_BASE}%g" changelog
         - sed -i -r "s%\{\{DATE\}\}%$(date -R)%g" changelog
         - sed -i -r "s%\{\{URL\}\}%${CI_PROJECT_URL}%g" changelog
         - sed -i -r "s%\{\{STABILITY\}\}%${STABILITY}%g" changelog
         - sed -i -r "s%\{\{PRIORITY\}\}%${PRIORITY}%g" changelog
         ## copyright file
-        - sed -i -r "s%\{\{BIN_NAME\}\}%${BIN_NAME}%g" copyright
+        - sed -i -r "s%\{\{BIN_NAME\}\}%${BIN_NAME_BASE}%g" copyright
         ## return to bin folder
         - cd $BIN_FOLDER_DEBIAN_PKG_AND_SIGN
 
@@ -66,6 +67,8 @@
         - build:version
     script:
         - VERSION=$(cat $VERSION_FILE)
+        - !reference [ .get_version_dependent_vars, script ]
+
         - security unlock-keychain -p $SIGN_KEYCHAIN_PASSWORD $SIGN_LOGIN_KEYCHAIN_PATH
 
         - cd $BIN_FOLDER_MACOS_PKG_AND_SIGN
@@ -75,13 +78,13 @@
 
         # Package and notarize the app
         - xcrun notarytool store-credentials --apple-id $SIGN_APPLE_ID --team-id $SIGN_TEAM_ID --password $SIGN_APP_PASSWORD --keychain $SIGN_LOGIN_KEYCHAIN_PATH $SIGN_KEYCHAIN_PROFILE
-        - ditto ${BIN_NAME} ${BIN_NAME}_pkg/usr/local/bin/
-        - productbuild --identifier $SIGN_IDENTIFIER --version $VERSION --sign $SIGN_DEV_ID_INST --keychain $SIGN_LOGIN_KEYCHAIN_PATH --timestamp --root ${BIN_NAME}_pkg / ${PKG_BIN_NAME_MACOS}
+        - ditto ${BIN_NAME} ${BIN_NAME_BASE}_pkg/usr/local/bin/${BIN_NAME_BASE}
+        - productbuild --identifier $SIGN_IDENTIFIER --version $VERSION --sign $SIGN_DEV_ID_INST --keychain $SIGN_LOGIN_KEYCHAIN_PATH --timestamp --root ${BIN_NAME_BASE}_pkg / ${PKG_BIN_NAME_MACOS}
         - xcrun notarytool submit ${BIN_NAME}.pkg --keychain $SIGN_LOGIN_KEYCHAIN_PATH --keychain-profile $SIGN_KEYCHAIN_PROFILE --wait
         - xcrun stapler staple ${BIN_NAME}.pkg
 
         # Clean folder
-        - rm -Rf ${BIN_NAME}_pkg
+        - rm -Rf ${BIN_NAME_BASE}_pkg
     artifacts:
         paths:
             - $ARTIFACTS_FOLDER/*
diff --git a/NodeApp/.gitlab-ci/05_stageTest.yml b/NodeApp/.gitlab-ci/05_stageTest.yml
index 4ad14ed93070394c518b813fe93a51b7b71efa78..914033e3daf27044c12958f49ffb58bd6a093e08 100644
--- a/NodeApp/.gitlab-ci/05_stageTest.yml
+++ b/NodeApp/.gitlab-ci/05_stageTest.yml
@@ -7,6 +7,7 @@ test:build:
         - apt update
         - apt install -y jq
         - !reference [ .get_version, script ]
+        - !reference [ .get_version_dependent_vars, script ]
 
         # Build
         - !reference [ .build_cli, script ]
diff --git a/NodeApp/.gitlab-ci/06_stageBuild.yml b/NodeApp/.gitlab-ci/06_stageBuild.yml
index 99e3dcf832b262481c11b17f3e34094bf0535f31..f1aeaa2e13cd5e49b54436ee79fcf96cc86d0cc8 100644
--- a/NodeApp/.gitlab-ci/06_stageBuild.yml
+++ b/NodeApp/.gitlab-ci/06_stageBuild.yml
@@ -7,6 +7,8 @@ build:version:
         - apt update
         - apt install -y jq
         - !reference [ .get_version, script ]
+        - !reference [ .get_version_dependent_vars, script ]
+
         - mkdir -p $ARTIFACTS_FOLDER
         - echo $VERSION > $VERSION_FILE
 
diff --git a/NodeApp/.gitlab-ci/08_stageClean.yml b/NodeApp/.gitlab-ci/08_stageClean.yml
index b1becbf50f4fffa4909ab5d116827e8fa2196926..0885aa18bbe5e7eac2a63f41b34e384aa8930317 100644
--- a/NodeApp/.gitlab-ci/08_stageClean.yml
+++ b/NodeApp/.gitlab-ci/08_stageClean.yml
@@ -5,6 +5,7 @@ clean:release:
     image: registry.gitlab.com/gitlab-ci-utils/curl-jq:latest
     script:
         - !reference [ .get_version, script ]
+        - !reference [ .get_version_dependent_vars, script ]
         - !reference [ .clean_release, script ]
     rules:
         -   if: '$CI_COMMIT_REF_PROTECTED == "true"'
@@ -17,6 +18,7 @@ clean:packages:
     image: registry.gitlab.com/gitlab-ci-utils/curl-jq:latest
     script:
         - !reference [ .get_version, script ]
+        - !reference [ .get_version_dependent_vars, script ]
         - !reference [ .clean_packages, script ]
     rules:
         -   if: '$CI_COMMIT_REF_PROTECTED == "true"'
@@ -30,6 +32,7 @@ clean:dev:release:
     script:
         - !reference [ .get_version, script ]
         - VERSION="${VERSION}${VERSION_DEV_SUFFIX}"
+        - !reference [ .get_version_dependent_vars, script ]
         - !reference [ .clean_release, script ]
     rules:
         -   if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
@@ -43,6 +46,7 @@ clean:dev:packages:
     script:
         - !reference [ .get_version, script ]
         - VERSION="${VERSION}${VERSION_DEV_SUFFIX}"
+        - !reference [ .get_version_dependent_vars, script ]
         - !reference [ .clean_packages, script ]
     rules:
         -   if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
diff --git a/NodeApp/.gitlab-ci/09_stageUpload.yml b/NodeApp/.gitlab-ci/09_stageUpload.yml
index 9ebb3fdf89f0cd171cd0e878e04b9c560c2165ec..19b77df97d314f5f40fd8eacd133914249d16626 100644
--- a/NodeApp/.gitlab-ci/09_stageUpload.yml
+++ b/NodeApp/.gitlab-ci/09_stageUpload.yml
@@ -8,6 +8,7 @@ upload:packages:
     image: registry.gitlab.com/gitlab-ci-utils/curl-jq:latest
     script:
         - !reference [ .get_version, script ]
+        - !reference [ .get_version_dependent_vars, script ]
         - !reference [ .get_packages_url, script ]
 
         # macOS
@@ -40,6 +41,7 @@ upload:packages:wiki:
         - apk add xz
 
         - !reference [ .get_version, script ]
+        - !reference [ .get_version_dependent_vars, script ]
         - !reference [ .get_packages_url, script ]
 
         # Create archive
diff --git a/NodeApp/.gitlab-ci/10_stageRelease.yml b/NodeApp/.gitlab-ci/10_stageRelease.yml
index ab82f3e2ec96fbaecc6accc1d71f045604d5e4ef..d66bb5ae0e4b88cae9fdd47bb2d3905e32208fd9 100644
--- a/NodeApp/.gitlab-ci/10_stageRelease.yml
+++ b/NodeApp/.gitlab-ci/10_stageRelease.yml
@@ -9,6 +9,7 @@ release:wiki:
         - apk add jq
 
         - !reference [ .get_version, script ]
+        - !reference [ .get_version_dependent_vars, script ]
 
         # Define URL for the wiki in terms of project-agnostic predefined variables
         - WIKI_URL="${CI_SERVER_PROTOCOL}://project_${CI_PROJECT_ID}_bot:${GITLAB_PROJECT_ACCESS_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/${CI_PROJECT_PATH}.wiki.git"
@@ -53,6 +54,7 @@ release:gitlab:
     image: registry.gitlab.com/gitlab-ci-utils/curl-jq:latest
     script:
         - !reference [ .get_version, script ]
+        - !reference [ .get_version_dependent_vars, script ]
         - RELEASE_NAME=$VERSION
         - !reference [ .release_gitlab, script ]
     rules:
@@ -66,6 +68,7 @@ release:latest:gitlab:
     image: registry.gitlab.com/gitlab-ci-utils/curl-jq:latest
     script:
         - !reference [ .get_version, script ]
+        - !reference [ .get_version_dependent_vars, script ]
         - RELEASE_NAME="Latest"
         - !reference [ .release_gitlab, script ]
     rules:
@@ -79,6 +82,7 @@ release:pre-alpha:gitlab:
     image: registry.gitlab.com/gitlab-ci-utils/curl-jq:latest
     script:
         - !reference [ .get_version, script ]
+        - !reference [ .get_version_dependent_vars, script ]
         - RELEASE_NAME="Pre-alpha"
         - !reference [ .release_gitlab, script ]
     rules:
diff --git a/NodeApp/package-lock.json b/NodeApp/package-lock.json
index 02fe3de63ed6c0ccc2dda7508a2d2d24783ab6d4..5fa193f14e3e973eddca8cf7af8fcac0e7b1c0ea 100644
--- a/NodeApp/package-lock.json
+++ b/NodeApp/package-lock.json
@@ -1,12 +1,12 @@
 {
     "name": "dojo_cli",
-    "version": "3.3.0",
+    "version": "3.4.1",
     "lockfileVersion": 3,
     "requires": true,
     "packages": {
         "": {
             "name": "dojo_cli",
-            "version": "3.3.0",
+            "version": "3.4.1",
             "license": "AGPLv3",
             "dependencies": {
                 "appdata-path": "^1.0.0",
diff --git a/NodeApp/package.json b/NodeApp/package.json
index ef5129535e233a31cc24b94dcb2f862fa929902c..fe5466e2f44a52dcf09f8bd37b9ee203d6b3cb1f 100644
--- a/NodeApp/package.json
+++ b/NodeApp/package.json
@@ -1,7 +1,7 @@
 {
     "name"           : "dojo_cli",
     "description"    : "CLI of the Dojo project",
-    "version"        : "3.3.0",
+    "version"        : "3.4.1",
     "license"        : "AGPLv3",
     "author"         : "Michaël Minelli <dojo@minelli.me>",
     "main"           : "dist/app.js",
diff --git a/NodeApp/src/managers/DojoBackendManager.ts b/NodeApp/src/managers/DojoBackendManager.ts
index d3711009cf433867a339eb495161397d895a0fd4..b8e8a41ec1beb1172244b281c61d658dc2c923ec 100644
--- a/NodeApp/src/managers/DojoBackendManager.ts
+++ b/NodeApp/src/managers/DojoBackendManager.ts
@@ -142,8 +142,12 @@ class DojoBackendManager {
             if ( verbose ) {
                 if ( error instanceof AxiosError ) {
                     if ( error.response ) {
-                        if ( error.response.status === StatusCodes.CONFLICT ) {
-                            spinner.fail(`You've already reached the max number of exercise of this assignment.`);
+                        if ( error.response.status === StatusCodes.INSUFFICIENT_SPACE_ON_RESOURCE ) {
+                            if ( error.response.data && (error.response.data as DojoBackendResponse<Array<GitlabUser>>).code === DojoStatusCode.MAX_EXERCISE_PER_ASSIGNMENT_REACHED ) {
+                                spinner.fail(`The following users have reached the maximum number of exercise of this assignment : ${ ((error.response.data as DojoBackendResponse<Array<GitlabUser>>).data as Array<GitlabUser>).map(user => user.name).join(', ') }.`);
+                            } else {
+                                spinner.fail(`You've already reached the max number of exercise of this assignment.`);
+                            }
                         } else {
                             if ( (error.response.data as DojoBackendResponse<unknown>).code === DojoStatusCode.EXERCISE_CREATION_GITLAB_ERROR ) {
                                 spinner.fail(`Exercise creation error: An unknown error occurred while creating the exercise on Gitlab. Please try again later or contact an administrator.`);
diff --git a/NodeApp/src/shared b/NodeApp/src/shared
index 89f3579ca9009f793742170928d808ab4c35d931..75f67b647da34337f3b220cacf78b2115d6022bc 160000
--- a/NodeApp/src/shared
+++ b/NodeApp/src/shared
@@ -1 +1 @@
-Subproject commit 89f3579ca9009f793742170928d808ab4c35d931
+Subproject commit 75f67b647da34337f3b220cacf78b2115d6022bc