diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index f1a55dc3f0acb1031982196149da8edcb1a2d6ef..fe7a8b12b998dab13c95cce183eec95e387ae6bc 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -1,23 +1,17 @@
-// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
-// https://github.com/microsoft/vscode-dev-containers/tree/v0.140.1/containers/puppet
 {
 	"name": "Puppet Development Kit (Community)",
 	"dockerFile": "Dockerfile",
 
-	// Set *default* container specific settings.json values on container create.
 	"settings": {
-		"terminal.integrated.shell.linux": "/bin/bash"
+		"terminal.integrated.profiles.linux": {
+			"bash": {
+				"path": "bash",
+			}
+		}
 	},
 
-	// Add the IDs of extensions you want installed when the container is created.
 	"extensions": [
 		"puppet.puppet-vscode",
 		"rebornix.Ruby"
 	]
-
-	// Use 'forwardPorts' to make a list of ports inside the container available locally.
-	// "forwardPorts": [],
-
-	// Use 'postCreateCommand' to run commands after the container is created.
-	// "postCreateCommand": "pdk --version",
 }
diff --git a/.rubocop.yml b/.rubocop.yml
index 8f782e741528905cd59743f73283f8a39e9bf210..31e8248ff813e956702d5c67844aeb0e2affc917 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -4,7 +4,7 @@ require:
 - rubocop-rspec
 AllCops:
   DisplayCopNames: true
-  TargetRubyVersion: '2.4'
+  TargetRubyVersion: '2.5'
   Include:
   - "**/*.rb"
   Exclude:
diff --git a/Gemfile b/Gemfile
index 18272fd72e8b95feb3fe64e34a51a9b75a7af794..0057a1722c6e185755de3802eef2da5c724db7c7 100644
--- a/Gemfile
+++ b/Gemfile
@@ -13,28 +13,39 @@ def location_for(place_or_version, fake_version = nil)
   end
 end
 
-ruby_version_segments = Gem::Version.new(RUBY_VERSION.dup).segments
-minor_version = ruby_version_segments[0..1].join('.')
-
 group :development do
-  gem "json", '= 2.0.4',                                         require: false if Gem::Requirement.create('~> 2.4.2').satisfied_by?(Gem::Version.new(RUBY_VERSION.dup))
-  gem "json", '= 2.1.0',                                         require: false if Gem::Requirement.create(['>= 2.5.0', '< 2.7.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup))
-  gem "json", '= 2.3.0',                                         require: false if Gem::Requirement.create(['>= 2.7.0', '< 2.8.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup))
-  gem "puppet-module-posix-default-r#{minor_version}", '~> 1.0', require: false, platforms: [:ruby]
-  gem "puppet-module-posix-dev-r#{minor_version}", '~> 1.0',     require: false, platforms: [:ruby]
-  gem "puppet-module-win-default-r#{minor_version}", '~> 1.0',   require: false, platforms: [:mswin, :mingw, :x64_mingw]
-  gem "puppet-module-win-dev-r#{minor_version}", '~> 1.0',       require: false, platforms: [:mswin, :mingw, :x64_mingw]
-  gem "puppet-lint-absolute_classname-check", '3.0.1',           require: false
-  gem "puppet-lint-absolute_template_path", '1.0.1',             require: false
-  gem "puppet-lint-empty_trailing_lines", '0.0.1',               require: false
-  gem "puppet-lint-file_ensure-check", '1.0.0',                  require: false
-  gem "puppet-lint-strict_indent-check", '2.0.8',                require: false
-  gem "puppet-lint-trailing_comma-check", '0.4.2',               require: false
-  gem "puppet-lint-unquoted_string-check", '2.1.0',              require: false
+  gem "json", '= 2.1.0',                                  require: false if Gem::Requirement.create(['>= 2.5.0', '< 2.7.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup))
+  gem "json", '= 2.3.0',                                  require: false if Gem::Requirement.create(['>= 2.7.0', '< 3.0.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup))
+  gem "json", '= 2.5.1',                                  require: false if Gem::Requirement.create(['>= 3.0.0', '< 3.0.5']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup))
+  gem "json", '= 2.6.1',                                  require: false if Gem::Requirement.create(['>= 3.1.0', '< 3.1.3']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup))
+  gem "json", '= 2.6.3',                                  require: false if Gem::Requirement.create(['>= 3.2.0', '< 4.0.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup))
+  gem "voxpupuli-puppet-lint-plugins", '~> 3.1',          require: false
+  gem "facterdb", '~> 1.18',                              require: false
+  gem "metadata-json-lint", '>= 2.0.2', '< 4.0.0',        require: false
+  gem "puppetlabs_spec_helper", '>= 3.0.0', '< 5.0.0',    require: false
+  gem "rspec-puppet-facts", '~> 2.0',                     require: false
+  gem "codecov", '~> 0.2',                                require: false
+  gem "dependency_checker", '~> 0.2',                     require: false
+  gem "parallel_tests", '~> 3.4',                         require: false
+  gem "pry", '~> 0.10',                                   require: false
+  gem "simplecov-console", '~> 0.5',                      require: false
+  gem "puppet-debugger", '~> 1.0',                        require: false
+  gem "rubocop", '= 1.6.1',                               require: false
+  gem "rubocop-performance", '= 1.9.1',                   require: false
+  gem "rubocop-rspec", '= 2.0.1',                         require: false
+  gem "rb-readline", '= 0.5.5',                           require: false, platforms: [:mswin, :mingw, :x64_mingw]
+  gem "concurrent-ruby", '< 1.2.0',                       require: false
+  gem "puppet-lint-absolute_classname-check", '>= 3.0.1', require: false
+  gem "puppet-lint-absolute_template_path", '>= 1.0.1',   require: false
+  gem "puppet-lint-empty_trailing_lines", '>= 0.0.1',     require: false
+  gem "puppet-lint-file_ensure-check", '>= 1.0.0',        require: false
+  gem "puppet-lint-strict_indent-check", '>= 2.0.8',      require: false
+  gem "puppet-lint-trailing_comma-check", '>= 0.4.3',     require: false
+  gem "puppet-lint-unquoted_string-check", '>= 2.1.0',    require: false
 end
 group :system_tests do
-  gem "puppet-module-posix-system-r#{minor_version}", '~> 1.0', require: false, platforms: [:ruby]
-  gem "puppet-module-win-system-r#{minor_version}", '~> 1.0',   require: false, platforms: [:mswin, :mingw, :x64_mingw]
+  gem "puppet_litmus", '< 1.0.0', require: false, platforms: [:ruby]
+  gem "serverspec", '~> 2.41',    require: false
 end
 
 puppet_version = ENV['PUPPET_GEM_VERSION']
diff --git a/Rakefile b/Rakefile
index 2906c15babbebe65d3ed29e72a07328609fefe8e..0f8754eb61e400db1d117cad5026f06d3ba6ff89 100644
--- a/Rakefile
+++ b/Rakefile
@@ -43,6 +43,7 @@ end
 
 PuppetLint.configuration.send('disable_relative')
 
+
 if Bundler.rubygems.find_name('github_changelog_generator').any?
   GitHubChangelogGenerator::RakeTask.new :changelog do |config|
     raise "Set CHANGELOG_GITHUB_TOKEN environment variable eg 'export CHANGELOG_GITHUB_TOKEN=valid_token_here'" if Rake.application.top_level_tasks.include? "changelog" and ENV['CHANGELOG_GITHUB_TOKEN'].nil?
diff --git a/data/common.yaml b/data/common.yaml
index 11d9b06014445601ec59cd4b69150c6ae6b11cae..e1414775418393cd29180542217ff61c22247ba4 100644
--- a/data/common.yaml
+++ b/data/common.yaml
@@ -25,3 +25,15 @@ aes::auth::keytab_devel: >
   6BI72YBgvod9N9z6P2iH0gFVVazciWTHVNcL4qZN4UHGDeBu5MH1wvTBZPpC
   IcAIbgvoQbriFHLJiL9HIWl6GSe6I/jp9n5veEkhHdT3M0nEEc0hbKWBaELj
   gTDWfQoET9V1Lrtv]
+
+aes::tal_cli::credentials: >
+  ENC[PKCS7,MIIBiQYJKoZIhvcNAQcDoIIBejCCAXYCAQAxggEhMIIBHQIBAD
+  AFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAii6nHpFM6+6aPuw1Qnawf77K7f
+  C5I+XqUJJBFxdiKq1VKDlcM3mme+MlB6cR7+GYYN1VRc7bQSTbmA80bdryBQ
+  zutD8KOvNWDytmdZhnDiboQEqSyuabdHjTlWRRONcENgMni5Vobmkr45JNDT
+  5PQcTdVAP9z7K0+1tcHnQFhQczkW3iBhSq47awLNQQA4EXzQRNvSbF+DogBT
+  2H62DEufNsn0Ca537PcAccRGILqJ1xS3i5h3SG0+dizx3XW1OxPXhmP+OXa/
+  /5BIgbJGSRen3BYEgQw1uXgIaQbmXa9gRWw8e9GS8eDYwXtkygTsSDyXATt2
+  VFwo8lT/XfMs2sczBMBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBCOn8Yp6O
+  diU5v1PVARi1m6gCAqYcAytahjgq8Prbq9bwqHAvw8XyNek07WiXM3WNj8VA
+  ==]
diff --git a/files/squid/helpers/rules.d/cplusplus.rules b/files/squid/helpers/rules.d/cplusplus.rules
index 1730bb6ef9c7247be2512fe7fed6f89faa07dd24..aea3cc32ff31e9400eca1eb9f234a82f19bcd4d3 100644
--- a/files/squid/helpers/rules.d/cplusplus.rules
+++ b/files/squid/helpers/rules.d/cplusplus.rules
@@ -18,3 +18,10 @@
 ^https?://en\.cppreference\.com/w/cpp/.*             true
 ^https?://en\.cppreference\.com/mwiki/index.php\?.*  true
 ^https?://en\.cppreference\.com/mwiki/load.php\?.*   true
+
+// cppreference duckgogo.com search
+^https?://duckduckgo\.com/\?sites=cppreference.com&q=.* true
+^https?://duckduckgo\.com/.*\.woff2                     true
+^https?://duckduckgo\.com/.*\.css                       true
+^https?://duckduckgo\.com/.*\.js                        true
+^https?://duckduckgo\.com/.*\.js\?.=.*                  true
diff --git a/files/squid/helpers/rules.d/java.rules b/files/squid/helpers/rules.d/java.rules
index c3aa81f78e88c47b259e6312a9a31411c6d4d974..784a0203827ef6cee29a9821a2e15e471824a2cd 100644
--- a/files/squid/helpers/rules.d/java.rules
+++ b/files/squid/helpers/rules.d/java.rules
@@ -1,5 +1,12 @@
 // Java API reference 
 ^https?://docs\.oracle\.com/javase/7/docs/api/.*  true
+^https?://docs\.oracle\.com/en/java/javase/11/docs/api/.*  true
+^https?://docs\.oracle\.com/en/dcommon/js/.*\.js true
+^https?://www\.oracleimg\.com/us/assets/metrics/ora_docs\.js true
+^https?://docs\.oracle\.com/favicon\.ico true
 
 // Ahmed Java API reference
 ^https?://www\.ida\.liu\.se/~TDDC77/extra/api-7/.*  true
+
+// TDDC77 mars-2022
+^https?://docs\.oracle\.com/en/java/javase/[0-9][0-9]*/docs/api/.* true
diff --git a/files/squid/helpers/rules.d/opendsa.rules b/files/squid/helpers/rules.d/opendsa.rules
index 893734b0a01403d2f91b60e15b985d96e14c6511..2305f5e7e27b90f1f49a5637561684ffaffb2176 100644
--- a/files/squid/helpers/rules.d/opendsa.rules
+++ b/files/squid/helpers/rules.d/opendsa.rules
@@ -19,3 +19,8 @@
 ^https?://code\.jquery\.com/ui/.*/jquery-ui.js$                       true
 ^https?://code\.jquery\.com/ui/.*/jquery-ui.min.js$                   true
 ^https?://d3js.org/d3-selection-multi.v1.min.js                       true
+
+// TDDD86
+^https?://www\.ida\.liu\.se/opendsa/Books/TDDD86F21/.* true
+^https?://www\.ida\.liu\.se/opendsa/.*                 true
+^https://fs\.liu\.se/adfs/.*                           false
diff --git a/files/squid/helpers/rules.d/python.rules b/files/squid/helpers/rules.d/python.rules
index fe051f0ebba53d50073defb9cda80060a913916a..b7d78da862e1156f6fc6fdfed77449e518a795a0 100644
--- a/files/squid/helpers/rules.d/python.rules
+++ b/files/squid/helpers/rules.d/python.rules
@@ -1,5 +1,5 @@
-// extra for TDDE24 2020-01-17
-^https?://docs\.python\.org/3(\.[0-9]{1,2})?/library/itertools.*   false
+// extra for TDDE24 2020-01-17 until 2022-02-15
+// ^https?://docs\.python\.org/3(\.[0-9]{1,2})?/library/itertools.*   false
 
 // Python library reference
 ^https?://docs\.python\.org/3(\.[0-9]{1,2})?/library/.*            true
@@ -11,3 +11,17 @@
 ^https?://docs\.python\.org/3(\.[0-9]{1,2})?/.*          true
 ^https?://docs\.python\.org/3(\.[0-9]{1,2})?/reference/.*          true
 ^https?://docs\.python\.org/3(\.[0-9]{1,2})?/genindex(-[A-Za-z0-9_]+)?\.html        true
+
+// extra for 732A80 2021-10-26
+^https?://numpy\.org/doc/stable/reference/.* true
+^https?://numpy\.org/doc/stable/_static/.* true
+^https?://numpy\.org/doc/stable/search.* true
+^https?://numpy\.org/doc/_static/.* true
+^https?://fonts.gstatic.com/s/.* true
+^https?://www\.tensorflow\.org/api_docs/python/.* true
+^https?://www\.tensorflow\.org/images/.* true
+
+// extra for 732A80 2022-02-16
+^https?://docs\.scipy\.org/doc/scipy/reference/.* true
+^https?://docs\.scipy\.org/doc/scipy/_static/.* true
+^https?://img\.shields\.io/badge/release-1.8.0-980F0F?style=for-the-badge true
diff --git a/files/squid/helpers/rules.d/rstudio.rules b/files/squid/helpers/rules.d/rstudio.rules
index ba7a8570f21cde15c4e4ac174c9e97d5fff5c6ac..7b9d48046b9d8e162cc3e6cb16eb79499e792c3b 100644
--- a/files/squid/helpers/rules.d/rstudio.rules
+++ b/files/squid/helpers/rules.d/rstudio.rules
@@ -6,18 +6,28 @@
 
 // ^https?://cran\.rstudio\.com/src/contrib/.*           true
 
+// 732G12
+^https?://repo\.anaconda\.com/.*  true
+^https?://conda\.anaconda\.com/.*  true
+^https?://storage\.googleapis\.com/tensorflow/.*  true
+
 // 732A51
-^https://bioconductor\.org/packages/.*  true
-^https://bioconductor\.org/biocLite\.R  true
+^https?://bioconductor\.org/packages/.*  true
+^https?://bioconductor\.org/biocLite\.R  true
 
 // 732G33
 ^https?://raw\.githubusercontent\.com/STIMALiU/KursRprgm/master/Labs/Tests/.* true
 
 // 732GA98
-^https?://plot\.ly/r/reference.*                       true
-^https?://ggplot2\.tidyverse\.org/.*                    true
+^https?://plot\.ly/r/reference.*                        true
+^https?://plotly\.com/r/reference/.*		        true
+^https?://plotly\.com/all_static/.*		        true
+^https?://ggplot2\.tidyverse\.org/.*		        true
 ^https?://shiny\.rstudio\.com/reference/shiny/.*        true
 ^https?://www\.jasondavies\.com/wordtree/.*             true
+^https?://www\.ida\.liu\.se/~732A98/.*			true
+^https?://www\.gpsvisualizer\.com/atlas\.html          false
+^https?://www\.gpsvisualizer\.com/.*                    true
 
 // For plot.ly
 ^https?://ajax\.googleapis\.com/ajax/libs/.*\.js         true
diff --git a/files/squid/helpers/rules.d/translate.rules b/files/squid/helpers/rules.d/translate.rules
index 3e3fd8a0ee56f2daaf5cf8fb9a555e245c97023a..fd328643709c5e46473eccd43425fcd1b3b79d29 100644
--- a/files/squid/helpers/rules.d/translate.rules
+++ b/files/squid/helpers/rules.d/translate.rules
@@ -1,7 +1,7 @@
 // google translate
 
 ^https?://translate\.google\.se/.*      true
-^https?://consent\.google\.se/.*        true
+^https?://translate\.google\.com/.*	true
 
 ^https?://ssl\.gstatic\.com/.*          true
 
@@ -10,3 +10,6 @@
 ^https?://accounts\.google\.com/.*      false
 
 ^https?://fonts\.googleapis\.com/.*     true
+
+^https?://consent\.google\.se/.* 	true
+^https?://consent\.youtube\.com/.* 	true
diff --git a/files/sudoers_aes b/files/sudoers_aes
index aa07290f00a6e12cf8a53e53f3621e568f2b5ec1..c348355c20405e19739743fb65cce4aec8682e01 100644
--- a/files/sudoers_aes
+++ b/files/sudoers_aes
@@ -1,8 +1,8 @@
 klaar36 ALL=(ALL) NOPASSWD: ALL
 filst04 ALL=(ALL) NOPASSWD: ALL
 
-User_Alias EXAM_ADMINS = torjo38, klaar36, vikol94, magni54, filst04
-Runas_Alias EXAM_USER = examadm, %examadm, opendsa, %opendsa
+User_Alias EXAM_ADMINS = torjo38, klaar36, vikol94, magni54, filst04, emmen85
+Runas_Alias EXAM_USER = examadm, %examadm, opendsa, %opendsa, squid, %squid
 
 Cmnd_Alias SERVICE_CMDS = /usr/bin/systemctl, /usr/bin/less
 
diff --git a/files/tal/on_update.sh b/files/tal/on_update.sh
new file mode 100644
index 0000000000000000000000000000000000000000..77b49af58930d33ad827d47d2ae730b1325b622e
--- /dev/null
+++ b/files/tal/on_update.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/bash
+
+cd source
+
+python3 -m pip install --user -r scripts/requirements.txt
+
+sed -i 's|url = \.\./database|url = https://oauth2:glpat-WeW_ytbQ83JMs2UnQmhe@gitlab.liu.se/upp-aes/database|' .gitmodules
+git submodule update --init
+git checkout .gitmodules
+
+make
+
+cd ..
+ln -s source/oracle oracle
+cp source/tal tal
diff --git a/files/tal/tal-cli b/files/tal/tal-cli
new file mode 100644
index 0000000000000000000000000000000000000000..dcd199a2b9fb9964758b06565abf892ac9700c93
--- /dev/null
+++ b/files/tal/tal-cli
@@ -0,0 +1,3 @@
+#!/usr/bin/bash
+
+exec sudo -u examadm /home/examadm/tal-cli/source/scripts/tal-cli.py "$@"
diff --git a/files/tal/tal-export b/files/tal/tal-export
new file mode 100644
index 0000000000000000000000000000000000000000..f00efefd0ce7b839dda05324103eefec4e3cc8a5
--- /dev/null
+++ b/files/tal/tal-export
@@ -0,0 +1,3 @@
+#!/usr/bin/bash
+
+exec sudo -u examadm /home/examadm/tal-cli/source/scripts/tal-export.py "$@"
diff --git a/manifests/aes_sw.pp b/manifests/aes_sw.pp
index d907ca2f141cd5e5d6291e387c19a49e1dc3f613..2bfa4847928646d0c2d8eb6d214437a0bbcfbd51 100644
--- a/manifests/aes_sw.pp
+++ b/manifests/aes_sw.pp
@@ -1,5 +1,4 @@
 class aes::aes_sw {
-
   $examadm_user = examadm
   $examadm_group = $examadm_user
   $examadm_home = "/home/${examadm_user}"
@@ -18,7 +17,7 @@ class aes::aes_sw {
     managehome => false,
     membership => inclusive,
     system     => true,
-    shell      => '/sbin/nologin',
+    shell      => '/bin/bash',
   }
 
   file { $examadm_home:
@@ -28,16 +27,34 @@ class aes::aes_sw {
     group  => $examadm_group,
   }
 
+  file { "${examadm_home}/.ssh":
+    ensure => directory,
+    mode   => '0700',
+    owner  => $examadm_user,
+    group  => $examadm_group,
+  }
+
+  file { "${examadm_home}/.ssh/authorized_keys":
+    ensure  => file,
+    mode    => '0600',
+    owner   => $examadm_user,
+    group   => $examadm_group,
+    content => @(SSHPUBKEY),
+      command="/home/examadm/tal-cli/source/scripts/tal-export.py --format ics --lookback 90 --lookahead 180",no-pty,no-user-rc,no-port-forwarding,no-agent-forwarding,no-X11-forwarding ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDJW4LP0av20r7lPXNgsftF9oaAXK41AvHyuHwybciZC/QBfTcmYif83563cTg0OzR/p+OSobiDM0odaaFYtP/8xbuVRz87X5bGYm2m8yHHqPxobHkT5g/faMkl9Fef+Al4EsT5tiaYMOhG2lj8XRYuwAb7qjoz3FFbs8TEPE7Sv+4BUCCH94taCuNYLXSxN1EXvw7VW6Ld5QXRFP53l2QUeTqE9oSii3BVrXlqqrLvNV/7nwdwyse4uhff4QrM9o4oc9FaQr8PLlPGxdlbSfIQJMVzHGpeDu0WLw+NqtLO1hsdlvQm7GrT/v8N7GJNKlsvhwnwUuMhTrB0yPMbbub1 klaar36@upp
+      command="/home/examadm/tal-cli/source/scripts/tal-export.py --written --format ics --lookback 90 --lookahead 180",no-pty,no-user-rc,no-port-forwarding,no-agent-forwarding,no-X11-forwarding ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILZ8aEAXw0tRcYrk1aqldepuC6tmdUYZuM270QdDF79o tal written exams to ics
+    | SSHPUBKEY
+  }
+
   file { '/etc/systemd/system/aes_login.service':
     ensure  => file,
     owner   => root,
     group   => root,
     mode    => '0644',
     content => @(LOGINSERVICE),
-    [Unit]
+          [Unit]
     Description=AES Login server
     After=network.target
-    
+
     [Service]
     Type=simple
     User=examadm
@@ -52,6 +69,7 @@ class aes::aes_sw {
   # todo: logrotate
   service { 'aes_login' :
     ensure => 'running',
+    enable => true,
   }
 
   file { '/etc/systemd/system/aes_ms.service':
@@ -60,10 +78,10 @@ class aes::aes_sw {
     group   => root,
     mode    => '0644',
     content => @(MSSERVICE),
-    [Unit]
+          [Unit]
     Description=AES Exam server
     After=network.target
-    
+
     [Service]
     Type=simple
     User=examadm
@@ -81,14 +99,26 @@ class aes::aes_sw {
     group   => root,
     mode    => '0700',
     content => @(MSCRON),
-    #!/bin/sh
+          #!/bin/sh
     /usr/bin/systemctl restart aes_ms
     | MSCRON
   }
 
+  file { '/etc/cron.daily/aes_login':
+    ensure  => file,
+    owner   => root,
+    group   => root,
+    mode    => '0700',
+    content => @(MSCRON),
+          #!/bin/sh
+    /usr/bin/systemctl restart aes_login
+    | MSCRON
+  }
+
   # todo: logrotate
   service { 'aes_ms' :
     ensure => 'running',
+    enable => true,
   }
 
   exec { 'script-repo-updated':
diff --git a/manifests/auth.pp b/manifests/auth.pp
index be636f5463f919987366c10a1831a3ad83c82adb..ae5ba62684f4ebce9b72e35671886bdb0948a2be 100644
--- a/manifests/auth.pp
+++ b/manifests/auth.pp
@@ -1,8 +1,7 @@
-class aes::auth(
+class aes::auth (
   Optional[String] $keytab_production = undef,
   Optional[String] $keytab_devel = undef
 ) {
-
   $auth_user = auth
   $auth_group = $auth_user
   $auth_home = "/srv/${auth_user}"
@@ -47,7 +46,7 @@ class aes::auth(
     comment    => 'Authentication server for AES',
     managehome => false,
     membership => inclusive,
-    groups     => [ 'aes_local_auth' ],
+    groups     => ['aes_local_auth'],
     system     => true,
     shell      => '/sbin/nologin',
   }
@@ -110,7 +109,7 @@ class aes::auth(
 
   exec { 'update-auth-repo' :
     command     => "/opt/utils/update_repo.sh ${auth_home}/src https://oauth2:F-agHaRXCdyFy38q4c-N@gitlab.liu.se/upp-aes/communication.git ${server_type}",
-    environment => [ "REPO_USER=${auth_user}", "REPO_GROUP=${auth_group}", "REPO_ON_UPDATE=${auth_home}/on_update.sh" ],
+    environment => ["REPO_USER=${auth_user}", "REPO_GROUP=${auth_group}", "REPO_ON_UPDATE=${auth_home}/on_update.sh"],
     # This command will need to run "on_update" as root in order to restart the service.
     user        => root,
     group       => root,
@@ -120,5 +119,6 @@ class aes::auth(
 
   service { $auth_service :
     ensure => 'running',
+    enable => true,
   }
 }
diff --git a/manifests/auth_keydb.pp b/manifests/auth_keydb.pp
index 72a808e05a22f7274e85e093d6d0148b9c4d3f2b..f7a0c5a130b1f91e8ba1cdd5d0cc76dd7ca48a5e 100644
--- a/manifests/auth_keydb.pp
+++ b/manifests/auth_keydb.pp
@@ -1,5 +1,4 @@
 class aes::auth_keydb {
-
   $keydb_user = auth_keydb
   $keydb_group = $keydb_user
   $keydb_home = "/srv/${keydb_user}"
@@ -20,7 +19,7 @@ class aes::auth_keydb {
     comment    => 'Authentication server for AES',
     managehome => false,
     membership => inclusive,
-    groups     => [ 'aes_local_auth' ],
+    groups     => ['aes_local_auth'],
     system     => true,
     shell      => '/sbin/nologin',
   }
@@ -50,7 +49,7 @@ class aes::auth_keydb {
 
   exec { 'update-keydb-repo' :
     command     => "/opt/utils/update_repo.sh ${keydb_home}/src https://oauth2:F-agHaRXCdyFy38q4c-N@gitlab.liu.se/upp-aes/communication.git ${server_type}",
-    environment => [ "REPO_USER=${keydb_user}", "REPO_GROUP=${keydb_group}", "REPO_ON_UPDATE=${keydb_home}/on_update.sh" ],
+    environment => ["REPO_USER=${keydb_user}", "REPO_GROUP=${keydb_group}", "REPO_ON_UPDATE=${keydb_home}/on_update.sh"],
     # This command will need to run "on_update" as root in order to restart the service.
     user        => root,
     group       => root,
@@ -60,6 +59,7 @@ class aes::auth_keydb {
 
   service { $keydb_service :
     ensure => 'running',
+    enable => true,
   }
 
   # These are temporary until the AdmC database is up and running.
@@ -74,4 +74,5 @@ class aes::auth_keydb {
 
   service { 'aes_temp_userdb' :
     ensure => 'running',
-}}
\ No newline at end of file
+  }
+}
diff --git a/manifests/broker.pp b/manifests/broker.pp
index 973989b813a655e6c33de66116f2dd91ddd1fa10..33724401235d0f0f36adee8374d29d9e8c76ac70 100644
--- a/manifests/broker.pp
+++ b/manifests/broker.pp
@@ -1,5 +1,4 @@
 class aes::broker {
-
   $broker_user = broker
   $broker_group = $broker_user
   $broker_home = "/srv/${broker_user}"
@@ -90,7 +89,7 @@ class aes::broker {
 
   exec { 'update-broker-repo' :
     command     => "/opt/utils/update_repo.sh ${broker_home}/src https://oauth2:F-agHaRXCdyFy38q4c-N@gitlab.liu.se/upp-aes/communication.git ${server_type}",
-    environment => [ "REPO_USER=${broker_user}", "REPO_GROUP=${broker_group}", "REPO_ON_UPDATE=${broker_home}/on_update.sh" ],
+    environment => ["REPO_USER=${broker_user}", "REPO_GROUP=${broker_group}", "REPO_ON_UPDATE=${broker_home}/on_update.sh"],
     # This command will need to run "on_update" as root in order to restart the service.
     user        => root,
     group       => root,
@@ -100,5 +99,6 @@ class aes::broker {
 
   service { $broker_service :
     ensure => 'running',
+    enable => true,
   }
 }
diff --git a/manifests/examfiles.pp b/manifests/examfiles.pp
index c2524187300dd4e919a06e307530309d068e614a..6571ba070d5e7a67871e4f02180201051baaefa3 100644
--- a/manifests/examfiles.pp
+++ b/manifests/examfiles.pp
@@ -1,7 +1,8 @@
 class aes::examfiles {
-
   include users::micis03
   include users::jondy94
+  include users::andma54
+  include users::tomre48
 
   group { 'liuitdrs' :
     ensure    => present,
@@ -16,11 +17,18 @@ class aes::examfiles {
     groups +> liuitdrs,
   }
 
+  User <| title == andma54 |> {
+    groups +> liuitdrs,
+  }
+
+  User <| title == tomre48 |> {
+    groups +> liuitdrs,
+  }
+
   file { '/examfiles' :
     ensure => directory,
     mode   => '0775',
     owner  => root,
     group  => liuitdrs,
   }
-
 }
diff --git a/manifests/init.pp b/manifests/init.pp
index e722866b50b58d73e57edcb24acff5b243d87e55..1e5903418e2475f2f8bb6fc9ec4ae8f17bc6f21e 100644
--- a/manifests/init.pp
+++ b/manifests/init.pp
@@ -1,6 +1,7 @@
 class aes {
   include aes::examfiles
   include aes::aes_sw
+  include aes::tal_cli
   include aes::opendsa
   include aes::squid_filter
   include aes::latex
@@ -12,6 +13,9 @@ class aes {
   package {
     [
       'devtoolset-7',
+      'gcc',
+      'gcc-c++',
+      'libaio',
       'python36',
     ]:
       ensure  => installed,
@@ -96,9 +100,15 @@ class aes {
     sshkey     => 'AAAAB3NzaC1yc2EAAAADAQABAAACAQDbYFQ5iuox4ZxjleyIR4Pebp045xV1AhcaGXLNsBAMEk08d5ExPVXdoTsNcV9aGDH3mMnhihe4d3bY8xh919n5f500VY6TI1BQKDYUq5HXxbgfl6AG96WntcRc8OIKo31hjMc4o+GPawgvpit7cWs4tWBAxoenJcB43m99AaVH6xd8e6DYC6os6Zv69hu+hD/01aFzJEnANAAsDRqr5b+LUy/qKeRWzT1zGSzWUOeJBHS9rGXHIPmgoOs7FMCtT3w/lzoehxDNCsOUG8aBBb4jH7zDB59fYE3bp55lxjx176AraFHv/H/hcB6EGkqyOyMppHi2B0uPRxlTFOtNVSHptqKINh9NMYAniv+ZUGylJZMSWSQkRSI7U65EvfOaLFTHB/+IBfWAaXjcA0fNcm3lG0tCRXg3rbpumQ2ikq23FpFzNHG+T+383pJjeOjvZB26ij5C+vZ+jEJyXyL528OjO8sOmHEeR6lyc2UjAeHbf7//+gv/bo7wDTSMZVySLKXVwxY+eCEAwh8aVQHCmwx/qWmfE9FuKYZ6AZfdCPpCSQOZY97aQTMMAcSgLV2sYrMim9QpylkH0h4RLhBo76w+83Cg1uprv1ypag0RXIOu+BV0gOHAa3DxhCgWtf9JR3B4YDAq8GaYuVRq9Q6c9+iPo+EmQEdbU+7X4Loj34auOw==', # lint:ignore:140chars
   }
 
+  ::users::liu_user { 'emmen85':
+    commonname => 'Emma Enocksson Svensson',
+    shell      => '/bin/bash',
+    sshkey     => 'AAAAB3NzaC1yc2EAAAADAQABAAABAQCsUKr53aCwErzsdhD/5oEQ4gWW51NgXa70Ow20Fnv/pyKAepDsIMCOB6kf1aET8LOlnq8Wyu0/52GGB38mO6cUzi7MLeWj7bg1Npq7b5/Uoaquq/dginoVQDc5RuJfmoy7PwmjKep/J2OIkCs8kD4sKbqN3ArCW555hgBvlGCdHxER1x2c5wGc2iuMCcbsfonOfORIxzCoiF4igfmuA1wpFZgyjBLuHn/SOtp85pD3nR0JSiaJWcMLB7IkWzXxvbpUWhDf7/gE4mwCDkOajY8zdG+aLkAZI0J1TJUGq50zji4OouwxxPW2JhpVl1KbRPqec+pVtdQIZstgUg3YbJGl', # lint:ignore:140chars
+  }
+
   ::server_firewall::rules_file { '45-permit_squid.rules':
     content => @(EOF),
-    service squid is tcp/3128
+          service squid is tcp/3128
     service sclogin is tcp/23431
     service aesmsi is tcp/23816
     service aesmso is tcp/23817
@@ -113,5 +123,4 @@ class aes {
     end policy
     |-EOF
   }
-
 }
diff --git a/manifests/latex.pp b/manifests/latex.pp
index a60733369c86a233fb8a11a24b868bea9e68fb6b..e2d1c8be03fd2deb50bd6b2be5f1a5dd5a839d93 100644
--- a/manifests/latex.pp
+++ b/manifests/latex.pp
@@ -1,5 +1,4 @@
 class aes::latex {
-
   package {
     [
       'texlive',
@@ -15,6 +14,4 @@ class aes::latex {
     ]:
       ensure  => installed,
   }
-
-
 }
diff --git a/manifests/opendsa.pp b/manifests/opendsa.pp
index c54b242937a39f17e94bab8793970ba7ee90265b..c2e623df5b1140a1f771465e4d94317e29ff4ac3 100644
--- a/manifests/opendsa.pp
+++ b/manifests/opendsa.pp
@@ -1,5 +1,4 @@
 class aes::opendsa {
-
   $opendsa_user = opendsa
   $opendsa_group = $opendsa_user
   $opendsa_home = "/srv/${opendsa_user}"
@@ -41,7 +40,7 @@ class aes::opendsa {
 
   exec { 'update-repo':
     command     => "/opt/utils/update_repo.sh ${opendsa_home}/OpenDSA https://oauth2:taNPRZid9Hv6jJtdW_T8@gitlab.liu.se/opendsa/OpenDSA.git exam",
-    environment => [ "REPO_USER=${opendsa_user}", "REPO_GROUP=${opendsa_group}", "REPO_ON_UPDATE=${opendsa_home}/on_update.sh" ],
+    environment => ["REPO_USER=${opendsa_user}", "REPO_GROUP=${opendsa_group}", "REPO_ON_UPDATE=${opendsa_home}/on_update.sh"],
     # This command will need to run "on_update" as root in order to restart the service.
     user        => root,
     group       => root,
@@ -63,5 +62,4 @@ class aes::opendsa {
   }
 
   # Ändra TDDD86-raden i rules.d/opendsa till "TDDD86[AB]_191219"
-
 }
diff --git a/manifests/squid_filter.pp b/manifests/squid_filter.pp
index b94f736acb232ae81d92ebba2fc3bb54757d6ecb..3e64c0cef8535ded5a578b063845e100e01f54d4 100644
--- a/manifests/squid_filter.pp
+++ b/manifests/squid_filter.pp
@@ -1,5 +1,4 @@
 class aes::squid_filter {
-
   package { 'squid' :
     ensure => 'present',
   }
@@ -63,6 +62,6 @@ class aes::squid_filter {
   # todo: logrotate
   service { 'squid' :
     ensure => 'running',
+    enable => true,
   }
-
 }
diff --git a/manifests/tal_cli.pp b/manifests/tal_cli.pp
new file mode 100644
index 0000000000000000000000000000000000000000..253226855e78ea74ef344b5fa73e8d2a88dbc736
--- /dev/null
+++ b/manifests/tal_cli.pp
@@ -0,0 +1,71 @@
+class aes::tal_cli (
+  Optional[String] $credentials = undef
+) {
+  file { '/home/examadm/tal-cli' :
+    ensure => directory,
+    owner  => examadm,
+    group  => examadm,
+    mode   => '0700',
+  }
+
+  file { '/home/examadm/bin/tal-cli' :
+    ensure => file,
+    owner  => examadm,
+    group  => examadm,
+    mode   => '0755',
+    source => "puppet:///modules/${module_name}/tal/tal-cli",
+  }
+
+  file { '/home/examadm/bin/tal-export' :
+    ensure => file,
+    owner  => examadm,
+    group  => examadm,
+    mode   => '0755',
+    source => "puppet:///modules/${module_name}/tal/tal-export",
+  }
+
+  file { '/home/examadm/tal-cli/.tal' :
+    ensure  => file,
+    owner   => examadm,
+    group   => examadm,
+    mode    => '0600',
+    content => $credentials,
+  }
+
+  file { '/home/examadm/tal-cli/on_update.sh' :
+    ensure => file,
+    owner  => examadm,
+    group  => examadm,
+    mode   => '0700',
+    source => "puppet:///modules/${module_name}/tal/on_update.sh",
+  }
+
+  exec { 'update-tal-repo' :
+    command     => '/opt/utils/update_repo.sh /home/examadm/tal-cli/source https://oauth2:glpat-bfpVssm_zFmt1YRW7cLz@gitlab.liu.se/upp-aes/tal-cli.git master',
+    environment => ['REPO_ON_UPDATE=/home/examadm/tal-cli/on_update.sh'],
+    user        => examadm,
+    group       => examadm,
+    cwd         => '/home/examadm/tal-cli',
+  }
+
+  file { '/etc/cron.daily/tal-remind' :
+    ensure  => file,
+    owner   => 'root',
+    group   => 'root',
+    mode    => '0700',
+    content => @(END),
+    #!/bin/bash
+    if [ "$(hostname)" = "aes-devel.edu.liu.se" ]
+    then
+        TO="klas.arvidsson@liu.se"
+    else
+        TO="inrapportering@ida.liu.se"
+    fi
+    if [ -e /home/examadm/ENABLE_TAL_REMINDERS ]
+    then
+        sudo -u examadm /home/examadm/tal-cli/scripts/tal-remind.py --to ${TO} --send
+        sudo -u examadm /home/examadm/tal-cli/scripts/tal-remind.py --to ${TO} --computer-exam --send
+    fi
+    | END
+  }
+}
diff --git a/metadata.json b/metadata.json
index b01ff50fc8501ea71fe6d677d6c5835fde581329..cb6c9a3c1d574c6a1eeb1ddde49db09cf9923184 100644
--- a/metadata.json
+++ b/metadata.json
@@ -26,7 +26,7 @@
       "version_requirement": ">= 6.21.0 < 8.0.0"
     }
   ],
-  "pdk-version": "2.2.0",
+  "pdk-version": "2.6.1",
   "template-url": "https://gitlab.it.liu.se/puppet-infra/pdk-templates.git#liu",
-  "template-ref": "heads/liu-0-gd8925d4"
+  "template-ref": "heads/liu-0-g09dd5f0"
 }