diff --git a/app/Config/CURLRequest.php b/app/Config/CURLRequest.php
new file mode 100644
index 0000000000000000000000000000000000000000..a0484ca7bbcc573a8f8207a12b61c6f2925fc84b
--- /dev/null
+++ b/app/Config/CURLRequest.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Config;
+
+use CodeIgniter\Config\BaseConfig;
+
+class CURLRequest extends BaseConfig
+{
+    /**
+     * --------------------------------------------------------------------------
+     * CURLRequest Share Options
+     * --------------------------------------------------------------------------
+     *
+     * Whether share options between requests or not.
+     *
+     * If true, all the options won't be reset between requests.
+     * It may cause an error request with unnecessary headers.
+     */
+    public bool $shareOptions = true;
+}
diff --git a/app/Config/Cache.php b/app/Config/Cache.php
index f08efbc61a550e2a76b33fedeef8b31180def632..4266fb6a289a3af1281db7d520b103766ed3e5cf 100644
--- a/app/Config/Cache.php
+++ b/app/Config/Cache.php
@@ -89,6 +89,18 @@ class Cache extends BaseConfig
      */
     public int $ttl = 60;
 
+    /**
+     * --------------------------------------------------------------------------
+     * Reserved Characters
+     * --------------------------------------------------------------------------
+     *
+     * A string of reserved characters that will not be allowed in keys or tags.
+     * Strings that violate this restriction will cause handlers to throw.
+     * Default: {}()/\@:
+     * Note: The default set is required for PSR-6 compliance.
+     */
+    public string $reservedCharacters = '{}()/\@:';
+
     /**
      * --------------------------------------------------------------------------
      * File settings
diff --git a/app/Config/Events.php b/app/Config/Events.php
index 549ab277589d4fb0fb8d270a705810995e25a648..9fd5f31189931c600badd745418f8c162115952b 100644
--- a/app/Config/Events.php
+++ b/app/Config/Events.php
@@ -6,6 +6,7 @@ namespace Config;
 
 use App\Entities\Actor;
 use App\Entities\Post;
+use App\Models\EpisodeModel;
 use CodeIgniter\Events\Events;
 use CodeIgniter\Exceptions\FrameworkException;
 use Modules\Auth\Entities\User;
@@ -131,11 +132,11 @@ Events::on('on_post_add', function ($post): void {
 
     if ($post->episode_id !== null) {
         if ($isReply) {
-            model('EpisodeModel', false)
+            model(EpisodeModel::class, false)
                 ->where('id', $post->episode_id)
                 ->increment('comments_count');
         } else {
-            model('EpisodeModel', false)
+            model(EpisodeModel::class, false)
                 ->where('id', $post->episode_id)
                 ->increment('posts_count');
         }
@@ -160,7 +161,7 @@ Events::on('on_post_remove', function ($post): void {
     }
 
     if ($episodeId = $post->episode_id) {
-        model('EpisodeModel', false)
+        model(EpisodeModel::class, false)
             ->where('id', $episodeId)
             ->decrement('posts_count');
     }
diff --git a/app/Config/Feature.php b/app/Config/Feature.php
new file mode 100644
index 0000000000000000000000000000000000000000..25659ddd0c0d0a2e94b0d69d5f29be6bba67d2aa
--- /dev/null
+++ b/app/Config/Feature.php
@@ -0,0 +1,27 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Config;
+
+use CodeIgniter\Config\BaseConfig;
+
+/**
+ * Enable/disable backward compatibility breaking features.
+ */
+class Feature extends BaseConfig
+{
+    /**
+     * Enable multiple filters for a route or not
+     *
+     * If you enable this:
+     *   - CodeIgniter\CodeIgniter::handleRequest() uses:
+     *     - CodeIgniter\Filters\Filters::enableFilters(), instead of enableFilter()
+     *   - CodeIgniter\CodeIgniter::tryToRouteIt() uses:
+     *     - CodeIgniter\Router\Router::getFilters(), instead of getFilter()
+     *   - CodeIgniter\Router\Router::handle() uses:
+     *     - property $filtersInfo, instead of $filterInfo
+     *     - CodeIgniter\Router\RouteCollection::getFiltersForRoute(), instead of getFilterForRoute()
+     */
+    public bool $multipleFilters = false;
+}
diff --git a/app/Config/Filters.php b/app/Config/Filters.php
index b65ed212a885e06fd61d660873cb770d3252e9c2..a838f4dee0451b87d8d227e275fa83f3ac702484 100644
--- a/app/Config/Filters.php
+++ b/app/Config/Filters.php
@@ -8,6 +8,8 @@ use CodeIgniter\Config\BaseConfig;
 use CodeIgniter\Filters\CSRF;
 use CodeIgniter\Filters\DebugToolbar;
 use CodeIgniter\Filters\Honeypot;
+use CodeIgniter\Filters\InvalidChars;
+use CodeIgniter\Filters\SecureHeaders;
 use Modules\Auth\Filters\PermissionFilter;
 use Modules\Fediverse\Filters\FediverseFilter;
 use Myth\Auth\Filters\LoginFilter;
@@ -24,6 +26,8 @@ class Filters extends BaseConfig
         'csrf' => CSRF::class,
         'toolbar' => DebugToolbar::class,
         'honeypot' => Honeypot::class,
+        'invalidchars' => InvalidChars::class,
+        'secureheaders' => SecureHeaders::class,
         'login' => LoginFilter::class,
         'role' => RoleFilter::class,
         'permission' => PermissionFilter::class,
@@ -39,10 +43,13 @@ class Filters extends BaseConfig
         'before' => [
             // 'honeypot',
             // 'csrf',
+            // 'invalidchars',
         ],
         'after' => [
             'toolbar',
             // 'honeypot',
+            // 'honeypot',
+            // 'secureheaders',
         ],
     ];
 
diff --git a/app/Config/Generators.php b/app/Config/Generators.php
index 889825aa923922640c4b8b9200bc3b2240b15cc6..ea420233036e08d5e6a3f4431cb6d3078f01f32c 100644
--- a/app/Config/Generators.php
+++ b/app/Config/Generators.php
@@ -30,6 +30,7 @@ class Generators extends BaseConfig
     public array $views = [
         'make:command' =>
             'CodeIgniter\Commands\Generators\Views\command.tpl.php',
+        'make:config' => 'CodeIgniter\Commands\Generators\Views\config.tpl.php',
         'make:controller' =>
             'CodeIgniter\Commands\Generators\Views\controller.tpl.php',
         'make:entity' => 'CodeIgniter\Commands\Generators\Views\entity.tpl.php',
diff --git a/app/Config/Mimes.php b/app/Config/Mimes.php
index 5bb8faad002cb6009979df9d02c11d18f632a11d..bf94916e074bf7f1de828e5d84238c777d88fb59 100644
--- a/app/Config/Mimes.php
+++ b/app/Config/Mimes.php
@@ -309,11 +309,11 @@ class Mimes
      * @param string $proposedExtension - default extension (in case there is more than one with the same mime type)
      * @return string|null The extension determined, or null if unable to match.
      */
-    public static function guessExtensionFromType(string $type, string $proposedExtension = ''): ?string
+    public static function guessExtensionFromType(string $type, string $proposedExtension = null): ?string
     {
         $type = trim(strtolower($type), '. ');
 
-        $proposedExtension = trim(strtolower($proposedExtension));
+        $proposedExtension = trim(strtolower($proposedExtension ?? ''));
 
         if ($proposedExtension !== '') {
             if (array_key_exists($proposedExtension, static::$mimes) && in_array(
diff --git a/app/Config/Publisher.php b/app/Config/Publisher.php
new file mode 100644
index 0000000000000000000000000000000000000000..39018572c78c515507be842cc88af2a1b4629c2e
--- /dev/null
+++ b/app/Config/Publisher.php
@@ -0,0 +1,17 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Config;
+
+use CodeIgniter\Config\Publisher as BasePublisher;
+
+/**
+ * Publisher Configuration
+ *
+ * Defines basic security restrictions for the Publisher class to prevent abuse by injecting malicious files into a
+ * project.
+ */
+class Publisher extends BasePublisher
+{
+}
diff --git a/app/Config/Security.php b/app/Config/Security.php
index 9334bbe98762896e61ac2b966d6f4a5f028dc9e6..eedbb270f077d3259a6cfbb0c911f06b0b503ce3 100644
--- a/app/Config/Security.php
+++ b/app/Config/Security.php
@@ -8,12 +8,32 @@ use CodeIgniter\Config\BaseConfig;
 
 class Security extends BaseConfig
 {
+    /**
+     * --------------------------------------------------------------------------
+     * CSRF Protection Method
+     * --------------------------------------------------------------------------
+     *
+     * Protection Method for Cross Site Request Forgery protection.
+     *
+     * @var 'cookie'|'session'
+     */
+    public string $csrfProtection = 'cookie';
+
+    /**
+     * --------------------------------------------------------------------------
+     * CSRF Token Randomization
+     * --------------------------------------------------------------------------
+     *
+     * Randomize the CSRF Token for added security.
+     */
+    public bool $tokenRandomize = false;
+
     /**
      * --------------------------------------------------------------------------
      * CSRF Token Name
      * --------------------------------------------------------------------------
      *
-     * Token name for Cross Site Request Forgery protection cookie.
+     * Token name for Cross Site Request Forgery protection.
      */
     public string $tokenName = 'csrf_test_name';
 
@@ -22,7 +42,7 @@ class Security extends BaseConfig
      * CSRF Header Name
      * --------------------------------------------------------------------------
      *
-     * Token name for Cross Site Request Forgery protection cookie.
+     * Header name for Cross Site Request Forgery protection.
      */
     public string $headerName = 'X-CSRF-TOKEN';
 
@@ -31,7 +51,7 @@ class Security extends BaseConfig
      * CSRF Cookie Name
      * --------------------------------------------------------------------------
      *
-     * Cookie name for Cross Site Request Forgery protection cookie.
+     * Cookie name for Cross Site Request Forgery protection.
      */
     public string $cookieName = 'csrf_cookie_name';
 
@@ -51,7 +71,7 @@ class Security extends BaseConfig
      * CSRF Regenerate
      * --------------------------------------------------------------------------
      *
-     * Regenerate CSRF Token on every request.
+     * Regenerate CSRF Token on every submission.
      */
     public bool $regenerate = true;
 
diff --git a/app/Config/Toolbar.php b/app/Config/Toolbar.php
index bba751e32b7e1ce7b90c1ecc3c818c8499312b43..30a1d4b0f457b71c29d2461e3137811b92379b86 100644
--- a/app/Config/Toolbar.php
+++ b/app/Config/Toolbar.php
@@ -37,7 +37,8 @@ class Toolbar extends BaseConfig
      */
     public array $collectors = [
         Timers::class,
-        Database::class,
+        // TODO: uncomment when fixed: https://github.com/codeigniter4/CodeIgniter4/issues/5539
+        // Database::class,
         Logs::class,
         Views::class,
         // Cache::class,
@@ -46,6 +47,16 @@ class Toolbar extends BaseConfig
         Events::class,
     ];
 
+    /**
+     * --------------------------------------------------------------------------
+     * Collect Var Data
+     * --------------------------------------------------------------------------
+     *
+     * If set to false var data from the views will not be colleted. Useful to
+     * avoid high memory usage when there are lots of data passed to the view.
+     */
+    public bool $collectVarData = true;
+
     /**
      * --------------------------------------------------------------------------
      * Max History
diff --git a/app/Controllers/EpisodeCommentController.php b/app/Controllers/EpisodeCommentController.php
index 6bb1ef0e67909595d7e9eb52fc7d2ab743e40fa2..61fb6bac697f8063401ed4095fef05d907913eaf 100644
--- a/app/Controllers/EpisodeCommentController.php
+++ b/app/Controllers/EpisodeCommentController.php
@@ -16,6 +16,7 @@ use App\Entities\Podcast;
 use App\Libraries\CommentObject;
 use App\Models\EpisodeCommentModel;
 use App\Models\EpisodeModel;
+use App\Models\LikeModel;
 use App\Models\PodcastModel;
 use CodeIgniter\Exceptions\PageNotFoundException;
 use CodeIgniter\HTTP\RedirectResponse;
@@ -135,7 +136,7 @@ class EpisodeCommentController extends BaseController
         /**
          * get comment replies
          */
-        $commentReplies = model('CommentModel', false)
+        $commentReplies = model(EpisodeCommentModel::class, false)
             ->where('in_reply_to_id', service('uuid')->fromString($this->comment->id)->getBytes())
             ->orderBy('created_at', 'ASC');
 
@@ -167,7 +168,7 @@ class EpisodeCommentController extends BaseController
 
     public function attemptLike(): RedirectResponse
     {
-        model('LikeModel')
+        model(LikeModel::class)
             ->toggleLike(interact_as_actor(), $this->comment);
 
         return redirect()->back();
@@ -175,7 +176,7 @@ class EpisodeCommentController extends BaseController
 
     public function attemptReply(): RedirectResponse
     {
-        model('LikeModel')
+        model(LikeModel::class)
             ->toggleLike(interact_as_actor(), $this->comment);
 
         return redirect()->back();
diff --git a/app/Controllers/EpisodeController.php b/app/Controllers/EpisodeController.php
index fd09ffb64decbdd11ede6a2f928bbc85508433f4..c0d216fb878cefb9ea6bf007834a56a0ef0dd81d 100644
--- a/app/Controllers/EpisodeController.php
+++ b/app/Controllers/EpisodeController.php
@@ -16,6 +16,7 @@ use App\Libraries\NoteObject;
 use App\Libraries\PodcastEpisode;
 use App\Models\EpisodeModel;
 use App\Models\PodcastModel;
+use App\Models\PostModel;
 use CodeIgniter\Database\BaseBuilder;
 use CodeIgniter\Exceptions\PageNotFoundException;
 use CodeIgniter\HTTP\Response;
@@ -259,7 +260,7 @@ class EpisodeController extends BaseController
         /**
          * get comments: aggregated replies from posts referring to the episode
          */
-        $episodeComments = model('PostModel')
+        $episodeComments = model(PostModel::class)
             ->whereIn('in_reply_to_id', function (BaseBuilder $builder): BaseBuilder {
                 return $builder->select('id')
                     ->from(config('Fediverse')->tablesPrefix . 'posts')
diff --git a/app/Controllers/PodcastController.php b/app/Controllers/PodcastController.php
index 6d0b6c690e4349db0dde5f524e7b3cbb517c0da1..ccc786b3c302374c6d8bc5e051a3f0fec903bf18 100644
--- a/app/Controllers/PodcastController.php
+++ b/app/Controllers/PodcastController.php
@@ -275,11 +275,11 @@ class PodcastController extends BaseController
     {
         if ($this->podcast->type === 'serial') {
             // podcast is serial
-            $episodes = model('EpisodeModel')
+            $episodes = model(EpisodeModel::class)
                 ->where('`published_at` <= NOW()', null, false)
                 ->orderBy('season_number DESC, number ASC');
         } else {
-            $episodes = model('EpisodeModel')
+            $episodes = model(EpisodeModel::class)
                 ->where('`published_at` <= NOW()', null, false)
                 ->orderBy('published_at', 'DESC');
         }
diff --git a/app/Controllers/PostController.php b/app/Controllers/PostController.php
index 0edb02dca51d6402194b448c8744e7b08148a842..ee5320418ef818046b7dce8cd93372958db142b3 100644
--- a/app/Controllers/PostController.php
+++ b/app/Controllers/PostController.php
@@ -23,6 +23,7 @@ use CodeIgniter\I18n\Time;
 use Modules\Analytics\AnalyticsTrait;
 use Modules\Fediverse\Controllers\PostController as FediversePostController;
 use Modules\Fediverse\Entities\Post as FediversePost;
+use Modules\Fediverse\Models\FavouriteModel;
 
 class PostController extends FediversePostController
 {
@@ -184,7 +185,7 @@ class PostController extends FediversePostController
 
     public function attemptFavourite(): RedirectResponse
     {
-        model('FavouriteModel')->toggleFavourite(interact_as_actor(), $this->post);
+        model(FavouriteModel::class)->toggleFavourite(interact_as_actor(), $this->post);
 
         return redirect()->back();
     }
diff --git a/app/Entities/EpisodeComment.php b/app/Entities/EpisodeComment.php
index 4d4774e4ca880a8f3ba6e0867e9252533ee63e04..da10e9e7f8004c66a393b22699e38266e648dc76 100644
--- a/app/Entities/EpisodeComment.php
+++ b/app/Entities/EpisodeComment.php
@@ -10,6 +10,7 @@ declare(strict_types=1);
 
 namespace App\Entities;
 
+use App\Models\ActorModel;
 use App\Models\EpisodeCommentModel;
 use App\Models\EpisodeModel;
 use CodeIgniter\I18n\Time;
@@ -94,7 +95,7 @@ class EpisodeComment extends UuidEntity
         }
 
         if ($this->actor === null) {
-            $this->actor = model('ActorModel', false)
+            $this->actor = model(ActorModel::class, false)
                 ->getActorById($this->actor_id);
         }
 
@@ -129,7 +130,7 @@ class EpisodeComment extends UuidEntity
         }
 
         if ($this->reply_to_comment === null) {
-            $this->reply_to_comment = model('EpisodeCommentModel', false)
+            $this->reply_to_comment = model(EpisodeCommentModel::class, false)
                 ->getCommentById($this->in_reply_to_id);
         }
 
diff --git a/app/Entities/Podcast.php b/app/Entities/Podcast.php
index 67534ddb57bd9c66ba3f207ff0521cdf3d7c85d6..e46335d7dfe63ae70fda5dfb6e846f24577ef555 100644
--- a/app/Entities/Podcast.php
+++ b/app/Entities/Podcast.php
@@ -12,6 +12,7 @@ namespace App\Entities;
 
 use App\Entities\Media\Image;
 use App\Libraries\SimpleRSSElement;
+use App\Models\ActorModel;
 use App\Models\CategoryModel;
 use App\Models\EpisodeModel;
 use App\Models\MediaModel;
@@ -188,7 +189,7 @@ class Podcast extends Entity
         }
 
         if ($this->actor === null) {
-            $this->actor = model('ActorModel')
+            $this->actor = model(ActorModel::class)
                 ->getActorById($this->actor_id);
         }
 
diff --git a/app/Helpers/auth_helper.php b/app/Helpers/auth_helper.php
index 7346267353fd45722fed7064ba2da498488026d9..163002d97af0a43e49f3fef1ec181e229299c0a2 100644
--- a/app/Helpers/auth_helper.php
+++ b/app/Helpers/auth_helper.php
@@ -8,6 +8,7 @@ declare(strict_types=1);
  * @link       https://castopod.org/
  */
 
+use App\Models\ActorModel;
 use CodeIgniter\Database\Exceptions\DataException;
 use Modules\Auth\Entities\User;
 use Modules\Fediverse\Entities\Actor;
@@ -74,7 +75,7 @@ if (! function_exists('interact_as_actor')) {
 
         $session = session();
         if ($session->has('interact_as_actor_id')) {
-            return model('ActorModel')->getActorById($session->get('interact_as_actor_id'));
+            return model(ActorModel::class)->getActorById($session->get('interact_as_actor_id'));
         }
 
         return false;
diff --git a/app/Models/EpisodeCommentModel.php b/app/Models/EpisodeCommentModel.php
index 3440802513e2cc5c2e83944e4fe6c363b27164d4..7102e5e456bbb0af4e09e8f31e30142e33e71cf2 100644
--- a/app/Models/EpisodeCommentModel.php
+++ b/app/Models/EpisodeCommentModel.php
@@ -15,6 +15,7 @@ use App\Libraries\CommentObject;
 use CodeIgniter\Database\BaseBuilder;
 use Michalsn\Uuid\UuidModel;
 use Modules\Fediverse\Activities\CreateActivity;
+use Modules\Fediverse\Models\ActivityModel;
 
 class EpisodeCommentModel extends UuidModel
 {
@@ -100,7 +101,7 @@ class EpisodeCommentModel extends UuidModel
                 ->set('actor', $comment->actor->uri)
                 ->set('object', new CommentObject($comment));
 
-            $activityId = model('ActivityModel', false)
+            $activityId = model(ActivityModel::class, false)
                 ->newActivity(
                     'Create',
                     $comment->actor_id,
@@ -113,7 +114,7 @@ class EpisodeCommentModel extends UuidModel
 
             $createActivity->set('id', url_to('activity', $comment->actor->username, $activityId));
 
-            model('ActivityModel', false)
+            model(ActivityModel::class, false)
                 ->update($activityId, [
                     'payload' => $createActivity->toJSON(),
                 ]);
@@ -188,9 +189,9 @@ class EpisodeCommentModel extends UuidModel
         $data['data']['id'] = $uuid4->toString();
 
         if (! isset($data['data']['uri'])) {
-            $actor = model('ActorModel', false)
+            $actor = model(ActorModel::class, false)
                 ->getActorById((int) $data['data']['actor_id']);
-            $episode = model('EpisodeModel', false)
+            $episode = model(EpisodeModel::class, false)
                 ->find((int) $data['data']['episode_id']);
 
             $data['data']['uri'] = url_to('episode-comment', $actor->username, $episode->slug, $uuid4->toString());
diff --git a/app/Models/LikeModel.php b/app/Models/LikeModel.php
index 23ea790fe9d6f7ccd183c179d05a577fbe8897f6..7c0335165b44a6b5b232ac5c7188c8a866063c20 100644
--- a/app/Models/LikeModel.php
+++ b/app/Models/LikeModel.php
@@ -16,6 +16,7 @@ use Michalsn\Uuid\UuidModel;
 use Modules\Fediverse\Activities\LikeActivity;
 use Modules\Fediverse\Activities\UndoActivity;
 use Modules\Fediverse\Entities\Actor;
+use Modules\Fediverse\Models\ActivityModel;
 
 class LikeModel extends UuidModel
 {
@@ -64,7 +65,7 @@ class LikeModel extends UuidModel
             $likeActivity->set('actor', $actor->uri)
                 ->set('object', $comment->uri);
 
-            $activityId = model('ActivityModel')
+            $activityId = model(ActivityModel::class)
                 ->newActivity(
                     'Like',
                     $actor->id,
@@ -77,7 +78,7 @@ class LikeModel extends UuidModel
 
             $likeActivity->set('id', url_to('activity', $actor->username, $activityId));
 
-            model('ActivityModel')
+            model(ActivityModel::class)
                 ->update($activityId, [
                     'payload' => $likeActivity->toJSON(),
                 ]);
@@ -105,7 +106,7 @@ class LikeModel extends UuidModel
         if ($registerActivity) {
             $undoActivity = new UndoActivity();
             // FIXME: get like activity associated with the deleted like
-            $activity = model('ActivityModel')
+            $activity = model(ActivityModel::class)
                 ->where([
                     'type' => 'Like',
                     'actor_id' => $actor->id,
@@ -122,7 +123,7 @@ class LikeModel extends UuidModel
                 ->set('actor', $actor->uri)
                 ->set('object', $likeActivity);
 
-            $activityId = model('ActivityModel')
+            $activityId = model(ActivityModel::class)
                 ->newActivity(
                     'Undo',
                     $actor->id,
@@ -135,7 +136,7 @@ class LikeModel extends UuidModel
 
             $undoActivity->set('id', url_to('activity', $actor->username, $activityId));
 
-            model('ActivityModel')
+            model(ActivityModel::class)
                 ->update($activityId, [
                     'payload' => $undoActivity->toJSON(),
                 ]);
diff --git a/app/Views/errors/html/error_exception.php b/app/Views/errors/html/error_exception.php
index 5d4b8f8d46edafed577791918078fe667d2617b4..f26f54b6c42336b58a446d4f0c16bb0d1ee7fcf4 100644
--- a/app/Views/errors/html/error_exception.php
+++ b/app/Views/errors/html/error_exception.php
@@ -201,7 +201,7 @@ $errorId = uniqid('error', true); ?>
 					<tbody>
 						<tr>
 							<td style="width: 10em">Path</td>
-							<td><?= esc($request->uri) ?></td>
+							<td><?= esc($request->getUri()) ?></td>
 						</tr>
 						<tr>
 							<td>HTTP Method</td>
diff --git a/builds b/builds
index 08b02e16e5c0435a2dace180527b95228399454d..0b10a150ac59fc98539126de8173d938a305b31d 100644
--- a/builds
+++ b/builds
@@ -1,5 +1,6 @@
 #!/usr/bin/env php
 <?php
+
 define('LATEST_RELEASE', '^4.0');
 define('GITHUB_URL', 'https://github.com/codeigniter4/codeigniter4');
 
@@ -14,99 +15,81 @@ define('GITHUB_URL', 'https://github.com/codeigniter4/codeigniter4');
  */
 
 // Determine the requested stability
-if (empty($argv[1]) || !in_array($argv[1], ['release', 'development'])) {
+if (empty($argv[1]) || ! in_array($argv[1], ['release', 'development'], true)) {
     echo 'Usage: php builds [release|development]' . PHP_EOL;
-    exit();
+
+    exit;
 }
 
-$dev = $argv[1] == 'development';
+$dev = $argv[1] === 'development';
+
 $modified = [];
 
-/* Locate each file and update it for the requested stability */
+// Locate each file and update it for the requested stability
 
-// Composer.json
 $file = __DIR__ . DIRECTORY_SEPARATOR . 'composer.json';
 
 if (is_file($file)) {
-    // Make sure we can read it
-    if ($contents = file_get_contents($file)) {
-        if ($array = json_decode($contents, true)) {
-            // Development
+    $contents = file_get_contents($file);
+
+    if ((string) $contents !== '') {
+        $array = json_decode($contents, true);
+
+        if (is_array($array)) {
             if ($dev) {
-                // Set 'minimum-stability'
                 $array['minimum-stability'] = 'dev';
-                $array['prefer-stable'] = true;
+                $array['prefer-stable']     = true;
+                $array['repositories']      = $array['repositories'] ?? [];
 
-                // Make sure the repo is configured
-                if (!isset($array['repositories'])) {
-                    $array['repositories'] = [];
-                }
-
-                // Check for the CodeIgniter repo
                 $found = false;
+
                 foreach ($array['repositories'] as $repository) {
-                    if ($repository['url'] == GITHUB_URL) {
+                    if ($repository['url'] === GITHUB_URL) {
                         $found = true;
                         break;
                     }
                 }
 
-                // Add the repo if it was not found
-                if (!$found) {
+                if (! $found) {
                     $array['repositories'][] = [
                         'type' => 'vcs',
-                        'url' => GITHUB_URL,
+                        'url'  => GITHUB_URL,
                     ];
                 }
 
-                // Define the "require"
                 $array['require']['codeigniter4/codeigniter4'] = 'dev-develop';
                 unset($array['require']['codeigniter4/framework']);
-            }
-
-            // Release
-            else {
-                // Clear 'minimum-stability'
+            } else {
                 unset($array['minimum-stability']);
 
-                // If the repo is configured then clear it
                 if (isset($array['repositories'])) {
-                    // Check for the CodeIgniter repo
                     foreach ($array['repositories'] as $i => $repository) {
-                        if ($repository['url'] == GITHUB_URL) {
+                        if ($repository['url'] === GITHUB_URL) {
                             unset($array['repositories'][$i]);
                             break;
                         }
                     }
+
                     if (empty($array['repositories'])) {
                         unset($array['repositories']);
                     }
                 }
 
-                // Define the "require"
                 $array['require']['codeigniter4/framework'] = LATEST_RELEASE;
                 unset($array['require']['codeigniter4/codeigniter4']);
             }
 
-            // Write out a new composer.json
-            file_put_contents(
-                $file,
-                json_encode(
-                    $array,
-                    JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
-                ) . PHP_EOL
-            );
+            file_put_contents($file, json_encode($array, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . PHP_EOL);
+
             $modified[] = $file;
         } else {
-            echo 'Warning: Unable to decode composer.json! Skipping...' .
-                PHP_EOL;
+            echo 'Warning: Unable to decode composer.json! Skipping...' . PHP_EOL;
         }
     } else {
         echo 'Warning: Unable to read composer.json! Skipping...' . PHP_EOL;
     }
 }
 
-// Paths config and PHPUnit XMLs
 $files = [
     __DIR__ . DIRECTORY_SEPARATOR . 'app/Config/Paths.php',
     __DIR__ . DIRECTORY_SEPARATOR . 'phpunit.xml.dist',
@@ -117,37 +100,26 @@ foreach ($files as $file) {
     if (is_file($file)) {
         $contents = file_get_contents($file);
 
-        // Development
         if ($dev) {
-            $contents = str_replace(
-                'vendor/codeigniter4/framework',
-                'vendor/codeigniter4/codeigniter4',
-                $contents
-            );
-        }
-
-        // Release
-        else {
-            $contents = str_replace(
-                'vendor/codeigniter4/codeigniter4',
-                'vendor/codeigniter4/framework',
-                $contents
-            );
+            $contents = str_replace('vendor/codeigniter4/framework', 'vendor/codeigniter4/codeigniter4', $contents);
+        } else {
+            $contents = str_replace('vendor/codeigniter4/codeigniter4', 'vendor/codeigniter4/framework', $contents);
         }
 
         file_put_contents($file, $contents);
+
         $modified[] = $file;
     }
 }
 
-if (empty($modified)) {
-    echo 'No files modified' . PHP_EOL;
+if ($modified === []) {
+    echo 'No files modified.' . PHP_EOL;
 } else {
     echo 'The following files were modified:' . PHP_EOL;
+
     foreach ($modified as $file) {
         echo " * {$file}" . PHP_EOL;
     }
-    echo 'Run `composer update` to sync changes with your vendor folder' .
-        PHP_EOL;
-}
 
+    echo 'Run `composer update` to sync changes with your vendor folder.' . PHP_EOL;
+}
diff --git a/composer.lock b/composer.lock
index 3b821cb03c3090cb05a8dba0024f4abce0c77222..309a845a8d50bbcd752b509a7b5b5f3385ce4483 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
     "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
     "This file is @generated automatically"
   ],
-  "content-hash": "afb6585b90ed08cc8a257f346ab1c416",
+  "content-hash": "9efed48a02371916c3615af689e1cba2",
   "packages": [
     {
       "name": "brick/math",
@@ -106,12 +106,12 @@
       "source": {
         "type": "git",
         "url": "https://github.com/codeigniter4/CodeIgniter4.git",
-        "reference": "995c51f383844bc44a607026ea6ab85b06c7e87e"
+        "reference": "0755553a4259fbacc799395ca8a5546c5e979c45"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/codeigniter4/CodeIgniter4/zipball/995c51f383844bc44a607026ea6ab85b06c7e87e",
-        "reference": "995c51f383844bc44a607026ea6ab85b06c7e87e",
+        "url": "https://api.github.com/repos/codeigniter4/CodeIgniter4/zipball/0755553a4259fbacc799395ca8a5546c5e979c45",
+        "reference": "0755553a4259fbacc799395ca8a5546c5e979c45",
         "shasum": ""
       },
       "require": {
@@ -119,22 +119,22 @@
         "ext-intl": "*",
         "ext-json": "*",
         "ext-mbstring": "*",
-        "kint-php/kint": "^3.3",
-        "laminas/laminas-escaper": "^2.6",
+        "kint-php/kint": "^4.0",
+        "laminas/laminas-escaper": "^2.9",
         "php": "^7.3 || ^8.0",
         "psr/log": "^1.1"
       },
       "require-dev": {
+        "codeigniter/coding-standard": "^1.1",
         "fakerphp/faker": "^1.9",
-        "friendsofphp/php-cs-fixer": "^3.0",
+        "friendsofphp/php-cs-fixer": "^3.1",
         "mikey179/vfsstream": "^1.6",
-        "nexusphp/cs-config": "^3.1",
+        "nexusphp/cs-config": "^3.3",
         "nexusphp/tachycardia": "^1.0",
-        "phpstan/phpstan": "0.12.88",
+        "phpstan/phpstan": "^1.0",
         "phpunit/phpunit": "^9.1",
         "predis/predis": "^1.1",
-        "rector/rector": "0.11.16",
-        "symplify/package-builder": "^9.3"
+        "rector/rector": "0.12.10"
       },
       "suggest": {
         "ext-fileinfo": "Improves mime type detection for files"
@@ -164,7 +164,15 @@
           "bash -c \"if [ -f admin/setup.sh ]; then bash admin/setup.sh; fi\""
         ],
         "analyze": ["phpstan analyse"],
-        "test": ["phpunit"]
+        "test": ["phpunit"],
+        "cs": [
+          "php-cs-fixer fix --verbose --dry-run --diff --config=.no-header.php-cs-fixer.dist.php",
+          "php-cs-fixer fix --verbose --dry-run --diff"
+        ],
+        "cs-fix": [
+          "php-cs-fixer fix --verbose --diff --config=.no-header.php-cs-fixer.dist.php",
+          "php-cs-fixer fix --verbose --diff"
+        ]
       },
       "license": ["MIT"],
       "description": "The CodeIgniter framework v4",
@@ -175,7 +183,7 @@
         "slack": "https://codeigniterchat.slack.com",
         "issues": "https://github.com/codeigniter4/CodeIgniter4/issues"
       },
-      "time": "2021-06-10T06:40:05+00:00"
+      "time": "2022-01-04T07:11:09+00:00"
     },
     {
       "name": "codeigniter4/settings",
@@ -587,24 +595,24 @@
     },
     {
       "name": "james-heinrich/getid3",
-      "version": "v2.0.0-beta4",
+      "version": "2.0.x-dev",
       "source": {
         "type": "git",
         "url": "https://github.com/JamesHeinrich/getID3.git",
-        "reference": "5ad79104e937e7d9c8a9141a97e1f063dd1123f8"
+        "reference": "ee238d552571c6029898b087d5fc95df826418d6"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/JamesHeinrich/getID3/zipball/5ad79104e937e7d9c8a9141a97e1f063dd1123f8",
-        "reference": "5ad79104e937e7d9c8a9141a97e1f063dd1123f8",
+        "url": "https://api.github.com/repos/JamesHeinrich/getID3/zipball/ee238d552571c6029898b087d5fc95df826418d6",
+        "reference": "ee238d552571c6029898b087d5fc95df826418d6",
         "shasum": ""
       },
       "require": {
         "php": ">=5.4.0"
       },
       "require-dev": {
-        "jakub-onderka/php-parallel-lint": "^0.9 || ^1.0",
-        "phpunit/phpunit": "^4.8|^5.0"
+        "php-parallel-lint/php-parallel-lint": "^1.0",
+        "phpunit/phpunit": "^4.8 || ^5.0 || ^6.1 || ^7.5 || ^8.5"
       },
       "suggest": {
         "ext-SimpleXML": "SimpleXML extension is required to analyze RIFF/WAV/BWF audio files (also requires `ext-libxml`).",
@@ -655,43 +663,37 @@
       "keywords": ["audio", "codecs", "id3", "metadata", "tags", "video"],
       "support": {
         "issues": "https://github.com/JamesHeinrich/getID3/issues",
-        "source": "https://github.com/JamesHeinrich/getID3/tree/v2.0.0-beta4"
+        "source": "https://github.com/JamesHeinrich/getID3/tree/2.0"
       },
-      "time": "2021-10-06T16:23:45+00:00"
+      "time": "2021-12-15T17:29:14+00:00"
     },
     {
       "name": "kint-php/kint",
-      "version": "3.3",
+      "version": "4.1.1",
       "source": {
         "type": "git",
         "url": "https://github.com/kint-php/kint.git",
-        "reference": "335ac1bcaf04d87df70d8aa51e8887ba2c6d203b"
+        "reference": "e64b939f9ceb9620abd982e2a66a3289fcf4e837"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/kint-php/kint/zipball/335ac1bcaf04d87df70d8aa51e8887ba2c6d203b",
-        "reference": "335ac1bcaf04d87df70d8aa51e8887ba2c6d203b",
+        "url": "https://api.github.com/repos/kint-php/kint/zipball/e64b939f9ceb9620abd982e2a66a3289fcf4e837",
+        "reference": "e64b939f9ceb9620abd982e2a66a3289fcf4e837",
         "shasum": ""
       },
       "require": {
-        "php": ">=5.3.6"
+        "php": ">=5.6"
       },
       "require-dev": {
-        "friendsofphp/php-cs-fixer": "^2.0",
-        "phpunit/phpunit": "^4.0",
+        "friendsofphp/php-cs-fixer": "^3.0",
+        "phpspec/prophecy-phpunit": "^2",
+        "phpunit/phpunit": "^9.0",
         "seld/phar-utils": "^1.0",
-        "symfony/finder": "^2.0 || ^3.0 || ^4.0",
-        "vimeo/psalm": "^3.0"
+        "symfony/finder": "^3.0 || ^4.0 || ^5.0",
+        "vimeo/psalm": "^4.0"
       },
       "suggest": {
-        "ext-ctype": "Simple data type tests",
-        "ext-iconv": "Provides fallback detection for ambiguous legacy string encodings such as the Windows and ISO 8859 code pages",
-        "ext-mbstring": "Provides string encoding detection",
-        "kint-php/kint-js": "Provides a simplified dump to console.log()",
-        "kint-php/kint-twig": "Provides d() and s() functions in twig templates",
-        "symfony/polyfill-ctype": "Replacement for ext-ctype if missing",
-        "symfony/polyfill-iconv": "Replacement for ext-iconv if missing",
-        "symfony/polyfill-mbstring": "Replacement for ext-mbstring if missing"
+        "kint-php/kint-twig": "Provides d() and s() functions in twig templates"
       },
       "type": "library",
       "autoload": {
@@ -707,10 +709,6 @@
           "name": "Jonathan Vollebregt",
           "homepage": "https://github.com/jnvsor"
         },
-        {
-          "name": "Rokas Šleinius",
-          "homepage": "https://github.com/raveren"
-        },
         {
           "name": "Contributors",
           "homepage": "https://github.com/kint-php/kint/graphs/contributors"
@@ -721,33 +719,32 @@
       "keywords": ["debug", "kint", "php"],
       "support": {
         "issues": "https://github.com/kint-php/kint/issues",
-        "source": "https://github.com/kint-php/kint/tree/master"
+        "source": "https://github.com/kint-php/kint/tree/4.1.1"
       },
-      "time": "2019-10-17T18:05:24+00:00"
+      "time": "2022-01-02T10:30:48+00:00"
     },
     {
       "name": "laminas/laminas-escaper",
-      "version": "2.7.0",
+      "version": "2.9.0",
       "source": {
         "type": "git",
         "url": "https://github.com/laminas/laminas-escaper.git",
-        "reference": "5e04bc5ae5990b17159d79d331055e2c645e5cc5"
+        "reference": "891ad70986729e20ed2e86355fcf93c9dc238a5f"
       },
       "dist": {
         "type": "zip",
-        "url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/5e04bc5ae5990b17159d79d331055e2c645e5cc5",
-        "reference": "5e04bc5ae5990b17159d79d331055e2c645e5cc5",
+        "url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/891ad70986729e20ed2e86355fcf93c9dc238a5f",
+        "reference": "891ad70986729e20ed2e86355fcf93c9dc238a5f",
         "shasum": ""
       },
       "require": {
-        "laminas/laminas-zendframework-bridge": "^1.0",
-        "php": "^7.3 || ~8.0.0"
+        "php": "^7.3 || ~8.0.0 || ~8.1.0"
       },
-      "replace": {
-        "zendframework/zend-escaper": "^2.6.1"
+      "conflict": {
+        "zendframework/zend-escaper": "*"
       },
       "require-dev": {
-        "laminas/laminas-coding-standard": "~1.0.0",
+        "laminas/laminas-coding-standard": "~2.3.0",
         "phpunit/phpunit": "^9.3",
         "psalm/plugin-phpunit": "^0.12.2",
         "vimeo/psalm": "^3.16"
@@ -781,60 +778,7 @@
           "type": "community_bridge"
         }
       ],
-      "time": "2020-11-17T21:26:43+00:00"
-    },
-    {
-      "name": "laminas/laminas-zendframework-bridge",
-      "version": "1.2.0",
-      "source": {
-        "type": "git",
-        "url": "https://github.com/laminas/laminas-zendframework-bridge.git",
-        "reference": "6cccbddfcfc742eb02158d6137ca5687d92cee32"
-      },
-      "dist": {
-        "type": "zip",
-        "url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/6cccbddfcfc742eb02158d6137ca5687d92cee32",
-        "reference": "6cccbddfcfc742eb02158d6137ca5687d92cee32",
-        "shasum": ""
-      },
-      "require": {
-        "php": "^7.3 || ^8.0"
-      },
-      "require-dev": {
-        "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.1 || ^9.3",
-        "psalm/plugin-phpunit": "^0.15.1",
-        "squizlabs/php_codesniffer": "^3.5",
-        "vimeo/psalm": "^4.6"
-      },
-      "type": "library",
-      "extra": {
-        "laminas": {
-          "module": "Laminas\\ZendFrameworkBridge"
-        }
-      },
-      "autoload": {
-        "files": ["src/autoload.php"],
-        "psr-4": {
-          "Laminas\\ZendFrameworkBridge\\": "src//"
-        }
-      },
-      "notification-url": "https://packagist.org/downloads/",
-      "license": ["BSD-3-Clause"],
-      "description": "Alias legacy ZF class names to Laminas Project equivalents.",
-      "keywords": ["ZendFramework", "autoloading", "laminas", "zf"],
-      "support": {
-        "forum": "https://discourse.laminas.dev/",
-        "issues": "https://github.com/laminas/laminas-zendframework-bridge/issues",
-        "rss": "https://github.com/laminas/laminas-zendframework-bridge/releases.atom",
-        "source": "https://github.com/laminas/laminas-zendframework-bridge"
-      },
-      "funding": [
-        {
-          "url": "https://funding.communitybridge.org/projects/laminas-project",
-          "type": "community_bridge"
-        }
-      ],
-      "time": "2021-02-25T21:54:58+00:00"
+      "time": "2021-09-02T17:10:53+00:00"
     },
     {
       "name": "league/commonmark",
diff --git a/env b/env
index 1106ce46f932ccf9fbc4117779f2c9fccb89bb2c..84a59a84e85ec4f5509500bc6aa1b652c37915cb 100644
--- a/env
+++ b/env
@@ -110,6 +110,8 @@
 # SECURITY
 #--------------------------------------------------------------------
 
+# security.csrfProtection = 'cookie'
+# security.tokenRandomize = false
 # security.tokenName = 'csrf_token_name'
 # security.headerName = 'X-CSRF-TOKEN'
 # security.cookieName = 'csrf_cookie_name'
@@ -123,3 +125,9 @@
 #--------------------------------------------------------------------
 
 # logger.threshold = 4
+
+#--------------------------------------------------------------------
+# CURLRequest
+#--------------------------------------------------------------------
+
+# curlrequest.shareOptions = true
diff --git a/phpstan.neon b/phpstan.neon
index f96db3c136d910b40d66b51033ac1aedc9b786a3..74274597e25d8c7515c37bb6b916b5d00fe2379c 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -30,6 +30,8 @@ parameters:
         - '#Function "property_exists\(\)" cannot be used/left in the code#'
         - '#Instead of "instanceof/is_a\(\)" use ReflectionProvider service or "\(new ObjectType\(<desired_type\>\)\)\-\>isSuperTypeOf\(<element_type\>\)" for static reflection to work#'
         - '#^Access to an undefined property App\\Entities\\Media\\Image#'
+        - '#^Call to an undefined method CodeIgniter\\Model#'
+        - '#^Access to an undefined property CodeIgniter\\Database\\BaseBuilder#'
         -
             message: '#Function "function_exists\(\)" cannot be used/left in the code#'
             paths:
diff --git a/tests/_support/DatabaseTestCase.php b/tests/_support/DatabaseTestCase.php
deleted file mode 100644
index 76b8b721125c85477d05750035edde43601403f5..0000000000000000000000000000000000000000
--- a/tests/_support/DatabaseTestCase.php
+++ /dev/null
@@ -1,61 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Tests\Support;
-
-use CodeIgniter\Test\CIUnitTestCase;
-use CodeIgniter\Test\DatabaseTestTrait;
-use Tests\Support\Database\Seeds\ExampleSeeder;
-
-/**
- * @phpstan-ignore-next-line
- */
-class DatabaseTestCase extends CIUnitTestCase
-{
-    use DatabaseTestTrait;
-
-    /**
-     * Should the database be refreshed before each test?
-     *
-     * @var boolean
-     */
-    protected $refresh = true;
-
-    /**
-     * The seed file(s) used for all tests within this test case. Should be fully-namespaced or relative to $basePath
-     *
-     * @var string|string[]
-     */
-    protected $seed = ExampleSeeder::class;
-
-    /**
-     * The path to the seeds directory. Allows overriding the default application directories.
-     *
-     * @var string
-     */
-    protected $basePath = SUPPORTPATH . 'Database/';
-
-    /**
-     * The namespace(s) to help us find the migration classes. Empty is equivalent to running `spark migrate -all`. Note
-     * that running "all" runs migrations in date order, but specifying namespaces runs them in namespace order (then
-     * date)
-     *
-     * @var string|string[]|null
-     */
-    protected $namespace = 'Tests\Support';
-
-    protected function setUp(): void
-    {
-        parent::setUp();
-
-        // Extra code to run before each test
-    }
-
-    protected function tearDown(): void
-    {
-        parent::tearDown();
-
-        // Extra code to run after each test
-    }
-}
diff --git a/tests/_support/SessionTestCase.php b/tests/_support/SessionTestCase.php
deleted file mode 100644
index 19e18bfd11a9d40cf016e744f627f6a9b843b8ad..0000000000000000000000000000000000000000
--- a/tests/_support/SessionTestCase.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Tests\Support;
-
-use CodeIgniter\Session\Handlers\ArrayHandler;
-use CodeIgniter\Session\SessionInterface;
-use CodeIgniter\Test\CIUnitTestCase;
-use CodeIgniter\Test\Mock\MockSession;
-use Config\Services;
-
-/**
- * @phpstan-ignore-next-line
- */
-class SessionTestCase extends CIUnitTestCase
-{
-    /**
-     * @var SessionInterface
-     */
-    protected $session;
-
-    protected function setUp(): void
-    {
-        parent::setUp();
-
-        $this->mockSession();
-    }
-
-    /**
-     * Pre-loads the mock session driver into $this->session.
-     *
-     * @var string
-     */
-    protected function mockSession(): void
-    {
-        $config = config('App');
-        $this->session = new MockSession(new ArrayHandler($config, '0.0.0.0'), $config,);
-        Services::injectMock('session', $this->session);
-    }
-}
diff --git a/tests/database/ExampleDatabaseTest.php b/tests/database/ExampleDatabaseTest.php
index 00b2709797db6983b129f4a09e76430b7dbae634..0108160da867e68f336075d0bc7861f9d520e051 100644
--- a/tests/database/ExampleDatabaseTest.php
+++ b/tests/database/ExampleDatabaseTest.php
@@ -4,17 +4,19 @@ declare(strict_types=1);
 
 namespace Tests\Database;
 
-use Tests\Support\DatabaseTestCase;
+use CodeIgniter\Test\CIUnitTestCase;
+use CodeIgniter\Test\DatabaseTestTrait;
+use Tests\Support\Database\Seeds\ExampleSeeder;
 use Tests\Support\Models\ExampleModel;
 
-class ExampleDatabaseTest extends DatabaseTestCase
+class ExampleDatabaseTest extends CIUnitTestCase
 {
-    protected function setUp(): void
-    {
-        parent::setUp();
+    use DatabaseTestTrait;
 
-        // Extra code to run before each test
-    }
+    /**
+     * @var string
+     */
+    protected $seed = ExampleSeeder::class;
 
     public function testModelFindAll(): void
     {
diff --git a/tests/session/ExampleSessionTest.php b/tests/session/ExampleSessionTest.php
index 63adeb2c340b5c3fb3b210d9cd959d26e48a6a56..6e2637ec2c8a056ec9c0d1851246e0258843a55c 100644
--- a/tests/session/ExampleSessionTest.php
+++ b/tests/session/ExampleSessionTest.php
@@ -4,21 +4,16 @@ declare(strict_types=1);
 
 namespace Tests\Session;
 
-use Tests\Support\SessionTestCase;
+use CodeIgniter\Test\CIUnitTestCase;
+use Config\Services;
 
-class ExampleSessionTest extends SessionTestCase
+class ExampleSessionTest extends CIUnitTestCase
 {
-    protected function setUp(): void
-    {
-        parent::setUp();
-    }
-
     public function testSessionSimple(): void
     {
-        $this->session->set('logged_in', 123);
-
-        $value = $this->session->get('logged_in');
+        $session = Services::session();
 
-        $this->assertSame(123, $value);
+        $session->set('logged_in', 123);
+        $this->assertSame(123, $session->get('logged_in'));
     }
 }
diff --git a/tests/unit/HealthTest.php b/tests/unit/HealthTest.php
index 0095448df36384eb414febb3c1d36a154f2132ff..06ea8eccfba7925fb421f79b64c8e4373ddb9610 100644
--- a/tests/unit/HealthTest.php
+++ b/tests/unit/HealthTest.php
@@ -2,35 +2,30 @@
 
 declare(strict_types=1);
 
-namespace Tests\Unit;
-
 use CodeIgniter\Test\CIUnitTestCase;
 use Config\App;
 use Config\Services;
 use Tests\Support\Libraries\ConfigReader;
 
-class HealthTest extends CIUnitTestCase
+/**
+ * @internal
+ */
+final class HealthTest extends CIUnitTestCase
 {
-    protected function setUp(): void
-    {
-        parent::setUp();
-    }
-
     public function testIsDefinedAppPath(): void
     {
-        $test = defined('APPPATH');
-
-        $this->assertTrue($test);
+        $this->assertTrue(defined('APPPATH'));
     }
 
     public function testBaseUrlHasBeenSet(): void
     {
         $validation = Services::validation();
+
         $env = false;
 
         // Check the baseURL in .env
         if (is_file(HOMEPATH . '.env')) {
-            $env = (bool) preg_grep('~^app\.baseURL = .~', file(HOMEPATH . '.env'),);
+            $env = preg_grep('~^app\.baseURL = .~', file(HOMEPATH . '.env')) !== false;
         }
 
         if ($env) {
@@ -40,7 +35,7 @@ class HealthTest extends CIUnitTestCase
             $config = new App();
             $this->assertTrue(
                 $validation->check($config->baseURL, 'valid_url'),
-                'baseURL "' . $config->baseURL . '" in .env is not valid URL',
+                'baseURL "' . $config->baseURL . '" in .env is not valid URL'
             );
         }
 
@@ -51,9 +46,7 @@ class HealthTest extends CIUnitTestCase
         // BaseURL in app/Config/App.php is a valid URL?
         $this->assertTrue(
             $validation->check($reader->baseURL, 'valid_url'),
-            'baseURL "' .
-                $reader->baseURL .
-                '" in app/Config/App.php is not valid URL',
+            'baseURL "' . $reader->baseURL . '" in app/Config/App.php is not valid URL'
         );
     }
 }