diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..ca5f2d6870dd0c486f27049bcadd9f7c86413f2d
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,155 @@
+[comment]: <> (Added = New features)
+[comment]: <> (Changed = Changes in existing functionality)
+[comment]: <> (Deprecated = once-stable features removed in future releases "next release")
+[comment]: <> (Removed = Deprecated features removed in this release "this release")
+[comment]: <> (Fixed = Bug fixes)
+# Changelog
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [Unreleased]
+### Added
+* Improved worker management: viewing logs is a single click, just like canceling or outright purging the worker. (!168)
+* An in-worker watchdog that terminates the worker if no ping response arrives within a set interval. (!168)
+* Submissions indicate whether their job was canceled. (!168)
+* Users can request the datetime their current token will expire. (!168)
+* An API endpoint, /api/v1/worker/events, that sends server-sent events with interesting happenings around workers. The UI uses these to update the Workers page, instead of hammering the getWorkers endpoint slightly faster than twice per second. (!168)
+### Changed
+* Exceptions raised within jobs now include the full stack trace and not just the message. (!168)
+* The checker routine no longer swallows analyzer exceptions. (!168)
+* The worker Python detector now also indicates the path to the found Python executables. (!168)
+* Worker shutdowns through messages now happen within three seconds (down from two minutes). (!168)
+* The CORS patch filter now also fires if Access-Control-Request-Headers is not present. (!168)
+* Killing all workers now happens in parallel to speed up shutdown. (!168)
+### Fixed
+* Concurrent logging on a worker that was causing crashes extremely rarely. (!168)
+
+## [2.3.4] - [2021-03-18]
+### Added
+* Docker container memory limit of 4 GiB (including swap) (!165)
+* Launched Docker containers are named by their job ID (!165)
+
+## [2.3.3] - [2021-03-16]
+### Added
+* In addition to the workers themselves, the core also checks for job timeouts (!162)
+
+## [2.3.2] - [2021-02-25]
+### Changed
+* Direct-upload no longer requires extensions and does not modify submission name (!159)
+### Deprecated
+* Misnamed 'identifier' param in direct-upload (!156)
+* Misnamed 'Auth-Token' header (!157)
+### Fixed
+* Plugin loader crashing if plugins directory did not exist (!154)
+* Python version and detection pattern being logged the wrong way around (!155)
+
+## [2.3.1] - [2020-09-28]
+### Fixed
+* Displacement was always required in assembly memory references (!151)
+
+## [2.3.0] - [2020-09-21]
+### Added
+* Core stores logs of its workers (!135)
+### Fixed
+* Various assembly analysis problems (!139, !146)
+
+## [2.2.0] - [2020-02-15]
+### Added
+* Script unit-testing (!125)
+* `JAVA_ARGS` and `AUTA_ARGS` for official Docker images to modify runtime arguments (!134)
+* Hiding feedback based on the viewer's authorization or report destination (!127)
+* Private, authenticated Docker registries (!140)
+* Job timeouts (!137)
+### Fixed
+* HTTP 500 if requests did not contain an Origin header
+
+## [2.1.0] - [2019-09-21]
+### Added
+* Course-level authorization (!126)
+### Fixed
+* STREW analyzer crashed on projects without tests (!124)
+* Project-level feedback not appearing on CPM and exported reports (!128)
+
+## [2.0.0] - [2019-07-03]
+### Changed
+* Default metric criteria scripts (existing assignments will not be modified) (!120) 
+### Fixed
+* Warning and failure counts being global, shared between jobs (!121)
+
+## [1.6.0] - [2019-07-02]
+### Added
+* Profanity checker (!110)
+* "AuTA score" badge generation (!116)
+* Docker container output parsing (!15)
+### Changed
+* Docker images can be started on different addresses (!105)
+* List of auto-generated worker names (!114)
+
+## [1.5.0] - [2019-06-17]
+### Added
+* Metric charts (!102)
+* Extracting of tar archives, uncompressed or compressed with gzip, bzip2, LZMA, XZ or Z (!99)
+### Changed
+* Empty entities (e.g., empty files) can be benchmarked and will use a fallback weight (!102)
+
+## [1.4.0] - [2019-06-09]
+### Added
+* Assignment summary exports (!80)
+* Exports by submitter identity (!83) 
+* Endpoint to view core logs (!89)
+* Organization by course (!81)
+* Language autodetection through GitHub Linguist (!90)
+* Submitter-configured suppressions (.auta.yml) (!91)
+* STREW (aggregated) metrics (!93)
+* User authorities can be changed (!101)
+### Changed
+* Default MongoDB database name changed from `results` to `auta` (!87)
+### Fixed
+* Submission pipeline logs appearing under the key `piplineLogs` (note the missing 'e') (!85)
+
+## [1.3.0] - [2019-05-29]
+### Added
+* Support for CORS where Spring doesn't natively (!24, !56)
+* Periodic security checks (!29)
+* MongoDB connection configuration (!30)
+* Test smell checking (!22)
+* Worker communication encryption (!33)
+* Workers without name, name themselves (!34)
+* Workers report their status through a Prometheus-compatible server (!39)
+* Metrics from the CK library (!46) and Radon (!50), replacing homebrew analyzers
+* Metrics benchmarking (!52, !62)
+* Duplicate code block detection (!54)
+* Python linting (!57)
+### Changed
+* Submission identity information is stored separately (!47)
+* Report generation uses a dedicated JS runtime, among other reporting enhancements (!48)
+* The core remembers the last set of supported metrics it got from a worker (!58)
+* Most API fields have length limits (!64)
+### Fixed
+* User password updates not being stored (!28)
+* Incomplete setting PUTs resetting unpopulated fields to defaults (!36)
+* Removed assignments preventing their name from being reused (!43)
+* Optionals not being serialized properly in API responses (!55)
+* Some endpoints returning incorrect error codes (!64)
+
+## [1.2.0] - [2019-05-10]
+### Added
+* Endpoint and UI to change users' passwords (!5)
+* A simple file count metric (!4)
+* Endpoint to list all workers (!10)
+* Endpoint to validate the authentication token (!11)
+* A direct-upload endpoint to simplify submission (!17)
+* Standalone HTML reports for exporting (!20)
+### Changed
+* x86_64-language assignments only accept .s files (!3)
+### Removed
+* Core no longer starts workers and orkers are single-threaded (can run only one job at a time) 
+  (!16)
+### Fixed
+* Spaces in file paths breaking jobs (!2)
+* Long reports no longer block workers and CPM is not called for jobs it didn't send (!19)
+
+## [0.1.0] - [2018-06-22]
+#### Initial release
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000000000000000000000000000000000000..d19f555e57a9357da0bf165c4f2f607cdb7a0627
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,75 @@
+# Contributing to AuTA #
+
+This contributing guide has the following objectives:
+1. [Getting Access](#getting-access)
+2. [Project Setup](#project-setup)
+3. [Project Architecture](#project-architecture)
+    1. [The Core](#the-core)
+    2. [The Workers](#the-workers)
+    3. [The Front-End](#the-front-end)
+4. [Working on AuTA](#working-on-auta)
+5. [Submitting Your Changes](#submitting-your-changes)
+
+## Getting Access ##
+
+To get started on developing AuTA (or Labrador), you will need to request access.
+We do this to prevent the project from becoming unmanageable and to keep track of bug bounties effectively.
+
+To request access, you will need to email eip-ewi@tudelft.nl. In this email, please explain why you want to help out with AuTA and what you want to contribute to specifically. Please also disclose your `gitlab.ewi.tudelft.nl` username.
+
+## Project Setup ##
+
+In order to get the project up and running, there is a few steps you need to take.
+
+1. Install [IntelliJ IDEA Professional](https://www.jetbrains.com/idea/) which is free for students.
+2. Install [Node.js](https://nodejs.org/en/download/) with NPM. Version 16 (LTS) is known to work.
+3. Clone the project into your local directory (`git clone <LINK_TO_GIT_REPOSITORY>`).
+4. Import the project into IntelliJ using the `build.gradle` file. Instructions can be found [here](https://www.jetbrains.com/help/idea/gradle.html#).
+5. Make sure that you are running [JDK 11](https://jdk.java.net/archive/), otherwise, IntelliJ won't run the project. Instructions on how to set this up can be found [here](https://www.jetbrains.com/help/idea/sdk.html#).
+6. Set up the application context.
+    1. Create a directory `/srv/auta` with read/write access for your user account;
+    2. Install MongoDB.
+7. To run the application:
+    1. Start the core via the `:core:bootRun` Gradle task (via the IDE or `./gradlew :core:bootRun`);
+    2. Request a worker token:
+       1. Go to http://localhost:8080/workers;
+       2. Log in with admin/admin;
+       3. Click "**+** New token".
+    3. Start one or more workers using this token. The recommended command line is:
+        ```shell
+        java -jar worker/build/libs/worker-<VERSION>.jar api-token=<API TOKEN> api-protocol=http api-port=8080
+        ```
+       * If local Docker support is needed, but the worker complains about a missing libjunixsocket object, add the following _before_ `-jar`: `-Dorg.newsclub.net.unix.library.override=worker/lib/jni/libjunixsocket-native-2.2.0.so`
+
+## Project Architecture ##
+
+See the [AuTA architecture overview](/doc/architecture-design/auta-subsystems.png) for a diagram.
+
+#### The Core ####
+
+The AuTA core is a [Spring Boot Application](https://spring.io/) and handles external requests such as new submissions and administration. It divides incoming jobs over its connected workers and stores and transforms their results into human-readable reports. Each installation has exactly one instance of the core.
+
+#### The Workers ####
+
+AuTA workers take incoming jobs for analysis, calculating the configured set of metrics of the submission and, if needed, launching a Docker container for further user-configurable analysis. Multiple workers can be associated with a core, which allows for wide scaling, even across machines and networks. Orchestration via [Kubernetes](https://kubernetes.io/) is also available if desired.
+
+#### The Front-End ####
+
+The front-end is a [Vue.js](https://v3.vuejs.org/) application that interacts with the core's REST API for configuring assignments and manual submissions. It is an optional component, as the REST API is sufficient to configure AuTA.
+
+## Working on AuTA ##
+
+There are a few things we'd like to ask you to do, to keep the project as organized and maintainable as possible. They are as follows:
+
+* **Sign your work.** If you are new to Labrador-dev, you will need to run a script which adds a `Signed-off-by` tag to each of your commits. Please read [these instructions](https://gitlab.ewi.tudelft.nl/eip/labrador/queue/-/blob/development/CONTRIBUTING.md#signing-your-work) to set this up.
+* **Keep your git history clean.**
+    * Please keep to the standard of writing commit messages: start with a capital letter and use the correct tense. You can imagine your commit message is a continuation of "This commit will...". Make sure each commit message clearly explains what you changed. Use commit titles to summarize the changes and the commit body to explain them in detail.
+    * Use `git rebase -i <BRANCH>` when rebasing on a different branch, if possible. Please avoid merging branches (unless you are making an MR to `development` or `master`) as this creates a messy commit history. If you are not familiar with rebasing, you can read the [documentation](https://git-scm.com/docs/git-rebase).
+* **Create your branch from the issue overview.** Open the issue you want to be working on and select the `Create branch` option. This way, the branch will be linked to the issue and once an MR from it is merged, it will automatically close it.
+* **List all your significant changes in the [changelog](CHANGELOG.md).**
+    * Log changes under the `[UNRELEASED]` tag.
+    * Make sure to put it under the correct category (`added` / `changed` / `fixed`).
+* **Make sure the code is properly formatted.** You can check you formatting by running `./gradlew checkstyleAll`. To keep reviews short, minimize the amount of changes; for example, do not align things by columns and do not auto-format files.
+* **Test you code.** Make sure you test all the code you write. We try to keep the test coverage as high as possible. To run the tests with gradle, you can run `./gradlew test` and to generate the reports, you can run `./gradlew jacocoRootReport`.
+* **Ensure your GitLab CI passes.** Your MR will not be able to merge if the pipelines on your MR don't pass. To check everything locally, run `./gradlew clean` followed by `./gradlew check`. Sometimes, one of the jobs in the CI doesn't pass due to a timeout - this might have been cause by a high load on the GitLab builders, so simply rerunning that job will often fix the issue.
+* **Write detailed issue and MR descriptions.** There are templates created for both issues and merge requests which you can fill in to keep your description as clear and informative as possible.
diff --git a/build.gradle b/build.gradle
index 4bb2df4d09bc1c9a49c26e1199aeb0b389aaba7d..632fb6cbb071c726d70e175a0baa25e3e57644c4 100644
--- a/build.gradle
+++ b/build.gradle
@@ -115,6 +115,9 @@ allprojects {
     }
 }
 
+task checkstyleAll {
+    dependsOn = [allprojects.checkstyleMain, allprojects.checkstyleTest]
+}
 
 task jacocoRootReport(type: org.gradle.testing.jacoco.tasks.JacocoReport) {
     dependsOn = allprojects.jacocoTestReport