diff --git a/VERSION b/VERSION
index 83e07c1..1a757d2 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.2410.211811
+0.2410.630130
diff --git a/composer.json b/composer.json
index 53212e3..93bd922 100644
--- a/composer.json
+++ b/composer.json
@@ -11,8 +11,8 @@
         "twig/html-extra": "^3.13"
     },
     "require-dev": {
-        "phpunit/phpunit": "^11.2",
-        "phpstan/phpstan": "^1.11"
+        "phpunit/phpunit": "^11.4",
+        "phpstan/phpstan": "^2.0"
     },
     "suggest": {
         "ext-memcache": "Support for the Index\\Cache\\Memcached namespace (only if you can't use ext-memcached for some reason).",
diff --git a/composer.lock b/composer.lock
index c5ccd3a..17f8eab 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,20 +4,20 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "e79de830674f6cbf86bf7874b086c7e0",
+    "content-hash": "a08a0c9bbd0fcba5c7e578f098486b06",
     "packages": [
         {
             "name": "symfony/deprecation-contracts",
-            "version": "v3.5.0",
+            "version": "v3.5.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/deprecation-contracts.git",
-                "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1"
+                "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
-                "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
+                "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
+                "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
                 "shasum": ""
             },
             "require": {
@@ -55,7 +55,7 @@
             "description": "A generic function and convention to trigger deprecation notices",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0"
+                "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1"
             },
             "funding": [
                 {
@@ -71,20 +71,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2024-04-18T09:32:20+00:00"
+            "time": "2024-09-25T14:20:29+00:00"
         },
         {
             "name": "symfony/mime",
-            "version": "v7.1.5",
+            "version": "v7.2.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/mime.git",
-                "reference": "711d2e167e8ce65b05aea6b258c449671cdd38ff"
+                "reference": "cc84a4b81f62158c3846ac7ff10f696aae2b524d"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/mime/zipball/711d2e167e8ce65b05aea6b258c449671cdd38ff",
-                "reference": "711d2e167e8ce65b05aea6b258c449671cdd38ff",
+                "url": "https://api.github.com/repos/symfony/mime/zipball/cc84a4b81f62158c3846ac7ff10f696aae2b524d",
+                "reference": "cc84a4b81f62158c3846ac7ff10f696aae2b524d",
                 "shasum": ""
             },
             "require": {
@@ -139,7 +139,7 @@
                 "mime-type"
             ],
             "support": {
-                "source": "https://github.com/symfony/mime/tree/v7.1.5"
+                "source": "https://github.com/symfony/mime/tree/v7.2.0"
             },
             "funding": [
                 {
@@ -155,7 +155,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2024-09-20T08:28:38+00:00"
+            "time": "2024-11-23T09:19:39+00:00"
         },
         {
             "name": "symfony/polyfill-ctype",
@@ -558,16 +558,16 @@
         },
         {
             "name": "twig/html-extra",
-            "version": "v3.13.0",
+            "version": "v3.16.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/twigphp/html-extra.git",
-                "reference": "8229e750091171c1f11801a525927811c7ac5a7e"
+                "reference": "2086023d3ffc4bae2b1115f715d17f97fd013665"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/twigphp/html-extra/zipball/8229e750091171c1f11801a525927811c7ac5a7e",
-                "reference": "8229e750091171c1f11801a525927811c7ac5a7e",
+                "url": "https://api.github.com/repos/twigphp/html-extra/zipball/2086023d3ffc4bae2b1115f715d17f97fd013665",
+                "reference": "2086023d3ffc4bae2b1115f715d17f97fd013665",
                 "shasum": ""
             },
             "require": {
@@ -610,7 +610,7 @@
                 "twig"
             ],
             "support": {
-                "source": "https://github.com/twigphp/html-extra/tree/v3.13.0"
+                "source": "https://github.com/twigphp/html-extra/tree/v3.16.0"
             },
             "funding": [
                 {
@@ -622,20 +622,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2024-09-03T13:08:40+00:00"
+            "time": "2024-09-30T06:41:48+00:00"
         },
         {
             "name": "twig/twig",
-            "version": "v3.14.0",
+            "version": "v3.16.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/twigphp/Twig.git",
-                "reference": "126b2c97818dbff0cdf3fbfc881aedb3d40aae72"
+                "reference": "475ad2dc97d65d8631393e721e7e44fb544f0561"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/twigphp/Twig/zipball/126b2c97818dbff0cdf3fbfc881aedb3d40aae72",
-                "reference": "126b2c97818dbff0cdf3fbfc881aedb3d40aae72",
+                "url": "https://api.github.com/repos/twigphp/Twig/zipball/475ad2dc97d65d8631393e721e7e44fb544f0561",
+                "reference": "475ad2dc97d65d8631393e721e7e44fb544f0561",
                 "shasum": ""
             },
             "require": {
@@ -646,6 +646,7 @@
                 "symfony/polyfill-php81": "^1.29"
             },
             "require-dev": {
+                "phpstan/phpstan": "^2.0",
                 "psr/container": "^1.0|^2.0",
                 "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0"
             },
@@ -689,7 +690,7 @@
             ],
             "support": {
                 "issues": "https://github.com/twigphp/Twig/issues",
-                "source": "https://github.com/twigphp/Twig/tree/v3.14.0"
+                "source": "https://github.com/twigphp/Twig/tree/v3.16.0"
             },
             "funding": [
                 {
@@ -701,22 +702,22 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2024-09-09T17:55:12+00:00"
+            "time": "2024-11-29T08:27:05+00:00"
         }
     ],
     "packages-dev": [
         {
             "name": "myclabs/deep-copy",
-            "version": "1.12.0",
+            "version": "1.12.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/myclabs/DeepCopy.git",
-                "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c"
+                "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c",
-                "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c",
+                "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845",
+                "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845",
                 "shasum": ""
             },
             "require": {
@@ -755,7 +756,7 @@
             ],
             "support": {
                 "issues": "https://github.com/myclabs/DeepCopy/issues",
-                "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0"
+                "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1"
             },
             "funding": [
                 {
@@ -763,7 +764,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2024-06-12T14:39:25+00:00"
+            "time": "2024-11-08T17:47:46+00:00"
         },
         {
             "name": "nikic/php-parser",
@@ -943,20 +944,20 @@
         },
         {
             "name": "phpstan/phpstan",
-            "version": "1.12.7",
+            "version": "2.0.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/phpstan/phpstan.git",
-                "reference": "dc2b9976bd8b0f84ec9b0e50cc35378551de7af0"
+                "reference": "46b4d3529b12178112d9008337beda0cc2a1a6b4"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/phpstan/phpstan/zipball/dc2b9976bd8b0f84ec9b0e50cc35378551de7af0",
-                "reference": "dc2b9976bd8b0f84ec9b0e50cc35378551de7af0",
+                "url": "https://api.github.com/repos/phpstan/phpstan/zipball/46b4d3529b12178112d9008337beda0cc2a1a6b4",
+                "reference": "46b4d3529b12178112d9008337beda0cc2a1a6b4",
                 "shasum": ""
             },
             "require": {
-                "php": "^7.2|^8.0"
+                "php": "^7.4|^8.0"
             },
             "conflict": {
                 "phpstan/phpstan-shim": "*"
@@ -997,7 +998,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2024-10-18T11:12:07+00:00"
+            "time": "2024-11-28T22:19:37+00:00"
         },
         {
             "name": "phpunit/php-code-coverage",
@@ -1324,16 +1325,16 @@
         },
         {
             "name": "phpunit/phpunit",
-            "version": "11.4.2",
+            "version": "11.4.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/phpunit.git",
-                "reference": "1863643c3f04ad03dcb9c6996c294784cdda4805"
+                "reference": "f9ba7bd3c9f3ff54ec379d7a1c2e3f13fe0bbde4"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1863643c3f04ad03dcb9c6996c294784cdda4805",
-                "reference": "1863643c3f04ad03dcb9c6996c294784cdda4805",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f9ba7bd3c9f3ff54ec379d7a1c2e3f13fe0bbde4",
+                "reference": "f9ba7bd3c9f3ff54ec379d7a1c2e3f13fe0bbde4",
                 "shasum": ""
             },
             "require": {
@@ -1343,7 +1344,7 @@
                 "ext-mbstring": "*",
                 "ext-xml": "*",
                 "ext-xmlwriter": "*",
-                "myclabs/deep-copy": "^1.12.0",
+                "myclabs/deep-copy": "^1.12.1",
                 "phar-io/manifest": "^2.0.4",
                 "phar-io/version": "^3.2.1",
                 "php": ">=8.2",
@@ -1354,7 +1355,7 @@
                 "phpunit/php-timer": "^7.0.1",
                 "sebastian/cli-parser": "^3.0.2",
                 "sebastian/code-unit": "^3.0.1",
-                "sebastian/comparator": "^6.1.1",
+                "sebastian/comparator": "^6.2.1",
                 "sebastian/diff": "^6.0.2",
                 "sebastian/environment": "^7.2.0",
                 "sebastian/exporter": "^6.1.3",
@@ -1404,7 +1405,7 @@
             "support": {
                 "issues": "https://github.com/sebastianbergmann/phpunit/issues",
                 "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
-                "source": "https://github.com/sebastianbergmann/phpunit/tree/11.4.2"
+                "source": "https://github.com/sebastianbergmann/phpunit/tree/11.4.4"
             },
             "funding": [
                 {
@@ -1420,7 +1421,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2024-10-19T13:05:19+00:00"
+            "time": "2024-11-27T10:44:52+00:00"
         },
         {
             "name": "sebastian/cli-parser",
@@ -1594,16 +1595,16 @@
         },
         {
             "name": "sebastian/comparator",
-            "version": "6.1.1",
+            "version": "6.2.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/comparator.git",
-                "reference": "5ef523a49ae7a302b87b2102b72b1eda8918d686"
+                "reference": "43d129d6a0f81c78bee378b46688293eb7ea3739"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5ef523a49ae7a302b87b2102b72b1eda8918d686",
-                "reference": "5ef523a49ae7a302b87b2102b72b1eda8918d686",
+                "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/43d129d6a0f81c78bee378b46688293eb7ea3739",
+                "reference": "43d129d6a0f81c78bee378b46688293eb7ea3739",
                 "shasum": ""
             },
             "require": {
@@ -1614,12 +1615,12 @@
                 "sebastian/exporter": "^6.0"
             },
             "require-dev": {
-                "phpunit/phpunit": "^11.3"
+                "phpunit/phpunit": "^11.4"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-main": "6.1-dev"
+                    "dev-main": "6.2-dev"
                 }
             },
             "autoload": {
@@ -1659,7 +1660,7 @@
             "support": {
                 "issues": "https://github.com/sebastianbergmann/comparator/issues",
                 "security": "https://github.com/sebastianbergmann/comparator/security/policy",
-                "source": "https://github.com/sebastianbergmann/comparator/tree/6.1.1"
+                "source": "https://github.com/sebastianbergmann/comparator/tree/6.2.1"
             },
             "funding": [
                 {
@@ -1667,7 +1668,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2024-10-18T15:00:48+00:00"
+            "time": "2024-10-31T05:30:08+00:00"
         },
         {
             "name": "sebastian/complexity",
@@ -2398,13 +2399,13 @@
     ],
     "aliases": [],
     "minimum-stability": "stable",
-    "stability-flags": [],
+    "stability-flags": {},
     "prefer-stable": false,
     "prefer-lowest": false,
     "platform": {
         "php": ">=8.3",
         "ext-mbstring": "*"
     },
-    "platform-dev": [],
+    "platform-dev": {},
     "plugin-api-version": "2.6.0"
 }
diff --git a/phpstan.neon b/phpstan.neon
index 39c5d92..f334b99 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -3,5 +3,7 @@ parameters:
   checkUninitializedProperties: true
   checkImplicitMixed: true
   checkBenevolentUnionTypes: true
+  treatPhpDocTypesAsCertain: false
   paths:
     - src
+    - tests
diff --git a/src/Cache/ArrayCache/ArrayCacheProvider.php b/src/Cache/ArrayCache/ArrayCacheProvider.php
index 2e7f826..98eb825 100644
--- a/src/Cache/ArrayCache/ArrayCacheProvider.php
+++ b/src/Cache/ArrayCache/ArrayCacheProvider.php
@@ -1,7 +1,7 @@
 <?php
 // ArrayCacheProvider.php
 // Created: 2024-04-10
-// Updated: 2024-10-19
+// Updated: 2024-12-02
 
 namespace Index\Cache\ArrayCache;
 
@@ -54,6 +54,8 @@ class ArrayCacheProvider implements CacheProvider {
     public function increment(string $key, int $amount = 1): int {
         $exists = array_key_exists($key, $this->items);
         $value = $exists ? unserialize($this->items[$key]['value']) : 0;
+        if(!is_int($value))
+            $value = 0;
         $value += $amount;
         $serialised = serialize($value);
 
@@ -65,9 +67,6 @@ class ArrayCacheProvider implements CacheProvider {
                 'ttl' => 0,
             ];
 
-        if(is_float($value))
-            $value = (int)$value;
-
         return $value;
     }
 
diff --git a/src/Cache/Memcached/MemcachedProviderLegacy.php b/src/Cache/Memcached/MemcachedProviderLegacy.php
index ac66dde..7de461f 100644
--- a/src/Cache/Memcached/MemcachedProviderLegacy.php
+++ b/src/Cache/Memcached/MemcachedProviderLegacy.php
@@ -1,7 +1,7 @@
 <?php
 // MemcachedProviderLegacy.php
 // Created: 2024-04-10
-// Updated: 2024-10-19
+// Updated: 2024-12-02
 
 namespace Index\Cache\Memcached;
 
@@ -72,7 +72,7 @@ class MemcachedProviderLegacy extends MemcachedProvider {
     public function increment(string $key, int $amount = 1): int {
         $key = $this->prefix . $key;
         $result = $this->memcache->increment($key, $amount);
-        if($result === false) { // @phpstan-ignore-line: PHP documentation states increment returns int|false
+        if($result === false) {
             $result = $amount;
             $this->memcache->set($key, serialize($result), 0);
         }
@@ -83,7 +83,7 @@ class MemcachedProviderLegacy extends MemcachedProvider {
     public function decrement(string $key, int $amount = 1): int {
         $key = $this->prefix . $key;
         $result = $this->memcache->decrement($key, $amount);
-        if($result === false) { // @phpstan-ignore-line: PHP documentation states decrement returns int|false
+        if($result === false) {
             $result = $amount * -1;
             $this->memcache->set($key, serialize($result), 0);
         }
diff --git a/src/Config/Config.php b/src/Config/Config.php
index d6874eb..4ae9d15 100644
--- a/src/Config/Config.php
+++ b/src/Config/Config.php
@@ -1,7 +1,7 @@
 <?php
 // Config.php
 // Created: 2023-10-20
-// Updated: 2024-10-04
+// Updated: 2024-12-02
 
 namespace Index\Config;
 
@@ -90,7 +90,7 @@ interface Config {
      *  :f - float
      *  :d - float
      *
-     * @param array<string|string[]> $specs Specification of what items to grab.
+     * @param array<string|array{0: string, 1?: mixed, 2?: string}> $specs Specification of what items to grab.
      * @throws InvalidArgumentException If $specs is malformed.
      * @return array<string, mixed> An associative array containing the retrieved values.
      */
diff --git a/src/Config/GetValuesTrait.php b/src/Config/GetValuesTrait.php
index 23937dd..07575b4 100644
--- a/src/Config/GetValuesTrait.php
+++ b/src/Config/GetValuesTrait.php
@@ -1,7 +1,7 @@
 <?php
 // GetValuesTrait.php
 // Created: 2023-10-20
-// Updated: 2024-10-04
+// Updated: 2024-12-02
 
 namespace Index\Config;
 
@@ -14,7 +14,7 @@ trait GetValuesTrait {
     /**
      * Format described in {@see Config::getValues}.
      *
-     * @param array<string|string[]> $specs
+     * @param array<string|array{0: string, 1?: mixed, 2?: string}> $specs Specification of what items to grab.
      * @throws InvalidArgumentException If $specs contains an invalid entry.
      * @return array<string, mixed>
      */
diff --git a/src/Db/MariaDb/MariaDbStatement.php b/src/Db/MariaDb/MariaDbStatement.php
index 4b9d644..52c397b 100644
--- a/src/Db/MariaDb/MariaDbStatement.php
+++ b/src/Db/MariaDb/MariaDbStatement.php
@@ -1,7 +1,7 @@
 <?php
 // MariaDbStatement.php
 // Created: 2021-05-02
-// Updated: 2024-10-19
+// Updated: 2024-12-02
 
 namespace Index\Db\MariaDb;
 
@@ -120,10 +120,11 @@ class MariaDbStatement implements DbStatement {
     }
 
     public function execute(): int|string {
-        $args = [''];
+        $types = '';
+        $args = [null];
 
         foreach($this->params as $key => $param) {
-            $args[0] .= $param->getBindType();
+            $types .= $param->getBindType();
             $type = $param->getDbType();
             $value = $param->getValue();
 
@@ -144,8 +145,10 @@ class MariaDbStatement implements DbStatement {
             $args[] = &${"value{$key}"};
         }
 
-        if(!empty($args[0]))
+        if(!empty($types)) {
+            $args[0] = $types;
             call_user_func_array([$this->statement, 'bind_param'], $args);
+        }
 
         if(!$this->statement->execute())
             throw new RuntimeException($this->getLastErrorString(), $this->getLastErrorCode());
diff --git a/src/Db/Sqlite/SqliteMariaDbPolyfill.php b/src/Db/Sqlite/SqliteMariaDbPolyfill.php
index d5e2cd5..c16dc4f 100644
--- a/src/Db/Sqlite/SqliteMariaDbPolyfill.php
+++ b/src/Db/Sqlite/SqliteMariaDbPolyfill.php
@@ -1,7 +1,7 @@
 <?php
 // SqliteMariaDbPolyfill.php
 // Created: 2024-10-21
-// Updated: 2024-10-21
+// Updated: 2024-12-02
 
 namespace Index\Db\Sqlite;
 
@@ -210,13 +210,13 @@ final class SqliteMariaDbPolyfill {
      *
      * @see https://mariadb.com/kb/en/unhex/
      * @param mixed $str Hex string.
-     * @return mixed Binary value.
+     * @return ?string Binary value.
      */
     public static function mdbUnhex(mixed $str): ?string {
         if(!is_scalar($str))
             return null;
 
-        $str = hex2bin($str);
+        $str = hex2bin((string)$str);
         if($str === false)
             return '';
 
diff --git a/src/Http/HttpMessageBuilder.php b/src/Http/HttpMessageBuilder.php
index b3d0e75..85be622 100644
--- a/src/Http/HttpMessageBuilder.php
+++ b/src/Http/HttpMessageBuilder.php
@@ -1,7 +1,7 @@
 <?php
 // HttpMessageBuilder.php
 // Created: 2022-02-08
-// Updated: 2024-10-02
+// Updated: 2024-12-02
 
 namespace Index\Http;
 
@@ -111,7 +111,6 @@ class HttpMessageBuilder {
      * Checks whether this HTTP message has body contents.
      *
      * @return bool true if it has body contents.
-     * @phpstan-impure
      */
     public function hasContent(): bool {
         return $this->content !== null;
diff --git a/src/MediaType.php b/src/MediaType.php
index ecee030..b3e72e2 100644
--- a/src/MediaType.php
+++ b/src/MediaType.php
@@ -1,7 +1,7 @@
 <?php
 // MediaType.php
 // Created: 2022-02-10
-// Updated: 2024-10-02
+// Updated: 2024-12-02
 
 namespace Index;
 
@@ -226,7 +226,8 @@ class MediaType implements Stringable, Comparable, Equatable {
                 $string .= ';';
                 if(is_string($key))
                     $string .= $key . '=';
-                $string .= $value;
+                if(is_scalar($value))
+                    $string .= (string)$value;
             }
 
         return $string;
diff --git a/src/UriBase64.php b/src/UriBase64.php
index c9645c8..0860a26 100644
--- a/src/UriBase64.php
+++ b/src/UriBase64.php
@@ -1,7 +1,7 @@
 <?php
 // UriBase64.php
 // Created: 2022-01-13
-// Updated: 2024-07-31
+// Updated: 2024-12-02
 
 namespace Index;
 
@@ -24,9 +24,9 @@ final class UriBase64 {
      *
      * @param string $string The encoded data.
      * @param bool $strict If the strict parameter is set to true then the base64_decode() function will return false if the input contains character from outside the base64 alphabet. Otherwise invalid characters will be silently discarded.
-     * @return string|false Returns the decoded data or false on failure. The returned data may be binary.
+     * @return string Returns the decoded data or false on failure. The returned data may be binary.
      */
-    public static function decode(string $string, bool $strict = false): string|false {
+    public static function decode(string $string, bool $strict = false): string {
         return base64_decode(str_pad(strtr($string, '-_', '+/'), strlen($string) % 4, '=', STR_PAD_RIGHT));
     }
 }
diff --git a/tests/BencodeSerialisableTest.php b/tests/BencodeSerialisableTest.php
index ee01992..86bd799 100644
--- a/tests/BencodeSerialisableTest.php
+++ b/tests/BencodeSerialisableTest.php
@@ -1,7 +1,7 @@
 <?php
 // BencodeSerialisableTest.php
 // Created: 2024-09-29
-// Updated: 2024-10-02
+// Updated: 2024-12-02
 
 declare(strict_types=1);
 
@@ -54,7 +54,8 @@ final class BencodeSerialisableTest extends TestCase {
             public mixed $nullValPresent = null;
 
             #[BencodeProperty]
-            public array $scalarVals = [null, 0, 1234, 12.34, 'str', true, false];
+            /** @var scalar[] */
+            public array $scalarVals = [null, 0, 1234, 12.34, 'str', true, false]; // @phpstan-ignore-line: idgi??
 
             #[BencodeProperty('stringVal_method')]
             public function getStringVal(): string {
@@ -111,7 +112,8 @@ final class BencodeSerialisableTest extends TestCase {
                 return null;
             }
 
-            #[BencodeProperty]
+            #[BencodeProperty] // @phpstan-ignore-line: idgi??
+            /** @return scalar[] */
             public function getScalarVals(): array {
                 return [null, 0, 1234, 12.34, 'str', true, false];
             }
@@ -154,11 +156,11 @@ final class BencodeSerialisableTest extends TestCase {
             use BencodeSerializableTrait;
 
             #[BencodeProperty('test1')]
-            #[BencodeProperty('test2')]
+            #[BencodeProperty('test2')] // @phpstan-ignore-line: this is meant to test the dupe exception
             public string $stringVal = 'string value';
 
             #[BencodeProperty('test3')]
-            #[BencodeProperty('test4')]
+            #[BencodeProperty('test4')] // @phpstan-ignore-line: this is meant to test the dupe exception
             public function getIntVal(): int {
                 return 1234;
             }
diff --git a/tests/BencodeTest.php b/tests/BencodeTest.php
index ffe7baa..df47872 100644
--- a/tests/BencodeTest.php
+++ b/tests/BencodeTest.php
@@ -1,7 +1,7 @@
 <?php
 // BencodeTest.php
 // Created: 2023-07-21
-// Updated: 2024-08-01
+// Updated: 2024-12-02
 
 declare(strict_types=1);
 
@@ -16,6 +16,7 @@ final class BencodeTest extends TestCase {
     public function testDecode(): void {
         $decoded = Bencode::decode(base64_decode(self::TORRENT));
 
+        $this->assertIsArray($decoded);
         $this->assertEquals(5, count($decoded));
 
         $this->assertArrayHasKey('announce', $decoded);
@@ -26,15 +27,23 @@ final class BencodeTest extends TestCase {
 
         $this->assertArrayHasKey('info', $decoded);
 
+        $this->assertIsArray($decoded['info']);
         $this->assertArrayHasKey('private', $decoded['info']);
         $this->assertEquals(1, $decoded['info']['private']);
 
         $decoded = Bencode::decode(base64_decode(self::TORRENT), associative: false);
 
-        $this->assertEquals('https://tracker.flashii.net/announce.php/meow', $decoded->announce);
-        $this->assertEquals(1689973664, $decoded->{'creation date'});
-        $this->assertEquals('this is the comments field', $decoded->comment);
-        $this->assertEquals(1, $decoded->info->private);
+        $this->assertIsObject($decoded);
+        $this->assertObjectHasProperty('announce', $decoded);
+        $this->assertEquals('https://tracker.flashii.net/announce.php/meow', $decoded->announce); // @phpstan-ignore-line: checked above
+        $this->assertObjectHasProperty('creation date', $decoded);
+        $this->assertEquals(1689973664, $decoded->{'creation date'}); // @phpstan-ignore-line: checked above
+        $this->assertObjectHasProperty('comment', $decoded);
+        $this->assertEquals('this is the comments field', $decoded->comment); // @phpstan-ignore-line: checked above
+        $this->assertObjectHasProperty('info', $decoded);
+        $this->assertIsObject($decoded->info); // @phpstan-ignore-line: checked above
+        $this->assertObjectHasProperty('private', $decoded->info);
+        $this->assertEquals(1, $decoded->info->private); // @phpstan-ignore-line: checked above
     }
 
     public function testEncode(): void {
diff --git a/tests/DbConfigTest.php b/tests/DbConfigTest.php
index 45d27d9..824bc11 100644
--- a/tests/DbConfigTest.php
+++ b/tests/DbConfigTest.php
@@ -1,13 +1,13 @@
 <?php
 // DbConfigTest.php
 // Created: 2023-10-20
-// Updated: 2024-10-04
+// Updated: 2024-12-02
 
 declare(strict_types=1);
 
 use PHPUnit\Framework\TestCase;
 use PHPUnit\Framework\Attributes\CoversClass;
-use Index\Config\{GetValueInfoTrait,GetValuesTrait,MutableConfigTrait};
+use Index\Config\{GetValueInfoTrait,GetValuesTrait,MutableConfigTrait,ScopedConfigValueInfo};
 use Index\Config\Db\{DbConfig,DbConfigValueInfo};
 use Index\Db\{DbBackends,DbConnection};
 
@@ -17,8 +17,8 @@ use Index\Db\{DbBackends,DbConnection};
 #[CoversClass(GetValueInfoTrait::class)]
 #[CoversClass(GetValuesTrait::class)]
 final class DbConfigTest extends TestCase {
-    private DbConnection $dbConn;
-    private DbConfig $config;
+    private DbConnection $dbConn; // @phpstan-ignore-line: defined by PHPunit in setUp()
+    private DbConfig $config; // @phpstan-ignore-line: defined by PHPunit in setUp()
 
     private const VALUES = [
         'private.allow_password_reset' => 'b:1;',
@@ -114,8 +114,10 @@ final class DbConfigTest extends TestCase {
         $expected = ['private.perm.cat' => 'user', 'private.perm.val' => 1];
         $values = [];
         $valueInfos = $scoped->getValueInfos(['cat', 'val', 'poop']);
-        foreach($valueInfos as $valueInfo)
+        foreach($valueInfos as $valueInfo) {
+            $this->assertInstanceOf(ScopedConfigValueInfo::class, $valueInfo);
             $values[$valueInfo->getRealName()] = $valueInfo->getValue();
+        }
 
         $this->assertEquals($expected, $values);
 
diff --git a/tests/FsConfigTest.php b/tests/FsConfigTest.php
index df1aa2a..ab08733 100644
--- a/tests/FsConfigTest.php
+++ b/tests/FsConfigTest.php
@@ -1,13 +1,13 @@
 <?php
 // FsConfigTest.php
 // Created: 2023-10-20
-// Updated: 2024-10-04
+// Updated: 2024-12-02
 
 declare(strict_types=1);
 
 use PHPUnit\Framework\TestCase;
 use PHPUnit\Framework\Attributes\CoversClass;
-use Index\Config\{GetValueInfoTrait,GetValuesTrait,ImmutableConfigTrait};
+use Index\Config\{GetValueInfoTrait,GetValuesTrait,ImmutableConfigTrait,ScopedConfigValueInfo};
 use Index\Config\Fs\{FsConfig,FsConfigValueInfo};
 
 #[CoversClass(FsConfig::class)]
@@ -141,8 +141,10 @@ final class FsConfigTest extends TestCase {
         $expected = ['chat:channels:passwd:name' => 'Password', 'chat:channels:passwd:password' => 'meow'];
         $values = [];
         $valueInfos = $scoped->getValueInfos(['name', 'password', 'minRank']);
-        foreach($valueInfos as $valueInfo)
+        foreach($valueInfos as $valueInfo) {
+            $this->assertInstanceOf(ScopedConfigValueInfo::class, $valueInfo);
             $values[$valueInfo->getRealName()] = $valueInfo->getValue();
+        }
 
         $this->assertEquals($expected, $values);
 
diff --git a/tests/JsonSerializableTest.php b/tests/JsonSerializableTest.php
index 8988151..5d65387 100644
--- a/tests/JsonSerializableTest.php
+++ b/tests/JsonSerializableTest.php
@@ -1,7 +1,7 @@
 <?php
 // JsonSerializableTest.php
 // Created: 2024-09-29
-// Updated: 2024-09-30
+// Updated: 2024-12-02
 
 declare(strict_types=1);
 
@@ -52,7 +52,8 @@ final class JsonSerializableTest extends TestCase {
             public mixed $nullValPresent = null;
 
             #[JsonProperty]
-            public array $scalarVals = [null, 0, 1234, 12.34, 'str', true, false];
+            /** @var scalar[] */
+            public array $scalarVals = [null, 0, 1234, 12.34, 'str', true, false]; // @phpstan-ignore-line: idgi??
 
             #[JsonProperty('stringVal_method')]
             public function getStringVal(): string {
@@ -109,7 +110,8 @@ final class JsonSerializableTest extends TestCase {
                 return null;
             }
 
-            #[JsonProperty]
+            #[JsonProperty] // @phpstan-ignore-line: idgi??
+            /** @return scalar[] */
             public function getScalarVals(): array {
                 return [null, 0, 1234, 12.34, 'str', true, false];
             }
@@ -152,11 +154,11 @@ final class JsonSerializableTest extends TestCase {
             use JsonSerializableTrait;
 
             #[JsonProperty('test1')]
-            #[JsonProperty('test2')]
+            #[JsonProperty('test2')] // @phpstan-ignore-line: this is meant to test the dupe exception
             public string $stringVal = 'string value';
 
             #[JsonProperty('test3')]
-            #[JsonProperty('test4')]
+            #[JsonProperty('test4')] // @phpstan-ignore-line: this is meant to test the dupe exception
             public function getIntVal(): int {
                 return 1234;
             }
diff --git a/tests/RouterTest.php b/tests/RouterTest.php
index 64e4f9f..796c38b 100644
--- a/tests/RouterTest.php
+++ b/tests/RouterTest.php
@@ -1,7 +1,7 @@
 <?php
 // RouterTest.php
 // Created: 2022-01-20
-// Updated: 2024-10-05
+// Updated: 2024-12-02
 
 declare(strict_types=1);
 
@@ -91,37 +91,37 @@ final class RouterTest extends TestCase {
             use RouteHandlerTrait;
 
             #[HttpGet('/')]
-            public function getIndex() {
+            public function getIndex(): string {
                 return 'index';
             }
 
             #[HttpPost('/avatar')]
-            public function postAvatar() {
+            public function postAvatar(): string {
                 return 'avatar';
             }
 
             #[HttpPut('/static')]
-            public static function putStatic() {
+            public static function putStatic(): string {
                 return 'static';
             }
 
             #[HttpGet('/meow')]
             #[HttpPost('/meow')]
-            public function multiple() {
+            public function multiple(): string {
                 return 'meow';
             }
 
             #[HttpMiddleware('/mw')]
-            public function useMw() {
+            public function useMw(): string {
                 return 'this intercepts';
             }
 
             #[HttpGet('/mw')]
-            public function getMw() {
+            public function getMw(): string {
                 return 'this is intercepted';
             }
 
-            public function hasNoAttr() {
+            public function hasNoAttr(): string {
                 return 'not a route';
             }
         };
diff --git a/tests/TemplatingTest.php b/tests/TemplatingTest.php
index dc95f4b..2b24685 100644
--- a/tests/TemplatingTest.php
+++ b/tests/TemplatingTest.php
@@ -1,7 +1,7 @@
 <?php
 // TemplatingTest.php
 // Created: 2024-08-04
-// Updated: 2024-10-04
+// Updated: 2024-12-02
 
 declare(strict_types=1);
 
@@ -34,9 +34,9 @@ final class TemplatingTest extends TestCase {
             'twig_version' => TwigEnvironment::VERSION,
         ]);
 
-        $env->addFilter('test_filter', fn($text) => ('filter:' . $text));
-        $env->addFunction('test_function', fn($text) => ('func:' . $text));
-        $env->addTest('test_test', fn($text) => $text === 'test');
+        $env->addFilter('test_filter', fn(string $text) => ('filter:' . $text));
+        $env->addFunction('test_function', fn(string $text) => ('func:' . $text));
+        $env->addTest('test_test', fn(string $text) => $text === 'test');
 
         $rendered = $env->render('TemplatingTest-rendered', [
             'local_var' => 'this var is local',
diff --git a/tests/XArrayTest.php b/tests/XArrayTest.php
index 666ee0e..014a00b 100644
--- a/tests/XArrayTest.php
+++ b/tests/XArrayTest.php
@@ -1,7 +1,7 @@
 <?php
 // XArrayTest.php
 // Created: 2021-04-26
-// Updated: 2024-07-31
+// Updated: 2024-12-02
 
 declare(strict_types=1);
 
@@ -31,14 +31,33 @@ final class XArrayTest extends TestCase {
         $array3 = [1 => 'a', 2 => 'b', 3 => 'c', 4 => 'd', 5 => 'e'];
         $array4 = ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5];
 
-        foreach(XArray::extractIterator($array1) as $key => $value)
+        foreach(XArray::extractIterator($array1) as $key => $value) {
+            $this->assertTrue(is_string($key) || is_int($key));
+            $this->assertIsArray($array1);
+            $this->assertArrayHasKey($key, $array1);
             $this->assertEquals($value, $array1[$key]);
-        foreach(XArray::extractIterator($array2) as $key => $value)
+        }
+
+        foreach(XArray::extractIterator($array2) as $key => $value) {
+            $this->assertTrue(is_string($key) || is_int($key));
+            $this->assertIsArray($array2);
+            $this->assertArrayHasKey($key, $array2);
             $this->assertEquals($value, $array2[$key]);
-        foreach(XArray::extractIterator($array3) as $key => $value)
+        }
+
+        foreach(XArray::extractIterator($array3) as $key => $value) {
+            $this->assertTrue(is_string($key) || is_int($key));
+            $this->assertIsArray($array3);
+            $this->assertArrayHasKey($key, $array3);
             $this->assertEquals($value, $array3[$key]);
-        foreach(XArray::extractIterator($array4) as $key => $value)
+        }
+
+        foreach(XArray::extractIterator($array4) as $key => $value) {
+            $this->assertTrue(is_string($key) || is_int($key));
+            $this->assertIsArray($array4);
+            $this->assertArrayHasKey($key, $array4);
             $this->assertEquals($value, $array4[$key]);
+        }
     }
 
     public function testEquals(): void {
@@ -109,13 +128,13 @@ final class XArrayTest extends TestCase {
         $array1 = ['Windows', 'Flashwave', 'Misaka Mikoto', 'Misuzu', 'Index', 'Kasane Teto', 'Some garbage'];
         $array2 = ['Misaka Mikoto', 'Kasane Teto', 'Some garbage'];
 
-        $this->assertTrue(XArray::sequenceEquals(XArray::where($array1, fn($value) => strpos($value, ' ') !== false), $array2));
+        $this->assertTrue(XArray::sequenceEquals(XArray::where($array1, fn($value) => is_string($value) && strpos($value, ' ') !== false), $array2));
     }
 
     public function testFirst(): void {
         $array = ['Windows', 'Flashwave', 'Misaka Mikoto', 'Misuzu', 'Index', 'Kasane Teto', 'Some garbage'];
 
-        $this->assertEquals(XArray::first($array, fn($value) => strpos($value, 't') !== false), 'Misaka Mikoto');
+        $this->assertEquals(XArray::first($array, fn($value) => is_string($value) && strpos($value, 't') !== false), 'Misaka Mikoto');
     }
 
     public function testSelect(): void {