diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index aa4d6ea..5c6fb8c 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -6,31 +6,36 @@
       "version": "5.12.0",
       "commands": [
         "dotnet-gitversion"
-      ]
+      ],
+      "rollForward": false
     },
     "thirdlicense": {
       "version": "1.3.1",
       "commands": [
         "thirdlicense"
-      ]
+      ],
+      "rollForward": false
     },
     "dotnet-reportgenerator-globaltool": {
       "version": "5.2.0",
       "commands": [
         "reportgenerator"
-      ]
+      ],
+      "rollForward": false
     },
     "docfx": {
-      "version": "2.74.0",
+      "version": "2.77.0",
       "commands": [
         "docfx"
-      ]
+      ],
+      "rollForward": false
     },
     "gitreleasemanager.tool": {
       "version": "0.16.0",
       "commands": [
         "dotnet-gitreleasemanager"
-      ]
+      ],
+      "rollForward": false
     }
   }
 }
\ No newline at end of file
diff --git a/.editorconfig b/.editorconfig
index a99dd8d..929f75b 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -241,6 +241,7 @@ dotnet_diagnostic.CA1303.severity = none # We don't translate exception and log
 dotnet_diagnostic.SA1025.severity = none # Allow spaces in comments to structure info
 dotnet_diagnostic.IDE0045.severity = suggestion # Simplify ifs
 dotnet_diagnostic.IDE0046.severity = suggestion # Simplify ifs
+dotnet_diagnostic.IDE0057.severity = suggestion # Slice can be simplified
 
 ### StyleCop
 dotnet_diagnostic.SA1101.severity = none # Do not force to prefix local calls with 'this'
@@ -267,6 +268,7 @@ dotnet_diagnostic.SA0001.severity = none # Disable documentation
 dotnet_diagnostic.SA1402.severity = none # Multiple types in the same file
 dotnet_diagnostic.SA1600.severity = none # Disable documentation
 dotnet_diagnostic.SA1601.severity = none # Disable documentation
+dotnet_diagnostic.SA1602.severity = none # Disable documentation
 dotnet_diagnostic.SA1201.severity = none # Allow enums inside classes
 dotnet_diagnostic.S1144.severity = none # Remove unused setter
 dotnet_diagnostic.S2094.severity = none # Remove empty class
diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml
index fad0d31..bd14c1d 100644
--- a/.github/workflows/build-and-release.yml
+++ b/.github/workflows/build-and-release.yml
@@ -15,7 +15,7 @@ jobs:
     name: "Build"
     uses: ./.github/workflows/build.yml
     with:
-      dotnet_version: '8.0.100'
+      dotnet_version: '8.0.401'
 
   # Preview release on push to develop only
   # Stable release on version tag push only
@@ -25,7 +25,7 @@ jobs:
     needs: build
     uses: ./.github/workflows/deploy.yml
     with:
-      dotnet_version: '8.0.100'
+      dotnet_version: '8.0.401'
       azure_nuget_feed: 'https://pkgs.dev.azure.com/SceneGate/SceneGate/_packaging/SceneGate-Preview/nuget/v3/index.json'
     secrets:
       nuget_preview_token: "az" # Dummy values as we use Azure DevOps
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 2f3fe24..7ebe64f 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -26,10 +26,15 @@ jobs:
           lfs: true
 
       - name: "Setup .NET SDK"
-        uses: actions/setup-dotnet@v3
+        uses: actions/setup-dotnet@v4
         with:
           dotnet-version: ${{ inputs.dotnet_version }}
 
+      - name: "Setup .NET 6.0 SDK"
+        uses: actions/setup-dotnet@v4
+        with:
+          dotnet-version: '6.0.425'
+
       - name: "Build and test"
         run: dotnet run --project build/orchestrator -- --target=Default --dotnet-configuration=Release
         env:
@@ -43,7 +48,7 @@ jobs:
 
       - name: "Publish artifacts to CI"
         if: ${{ matrix.is_main_build }}
-        uses: actions/upload-artifact@v3
+        uses: actions/upload-artifact@v4
         with:
           name: "Artifacts"
           retention-days: 7
@@ -53,6 +58,6 @@ jobs:
 
       - name: Publish docs artifact to CI
         if: ${{ matrix.is_main_build }}
-        uses: actions/upload-pages-artifact@v2
+        uses: actions/upload-pages-artifact@v3
         with:
           path: build/artifacts/docs
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 7039796..55b91e1 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -32,7 +32,7 @@ jobs:
     steps:
       - name: Deploy to GitHub Pages
         id: deployment
-        uses: actions/deploy-pages@v2
+        uses: actions/deploy-pages@v4
 
   push_artifacts:
     name: "Artifacts"
@@ -44,13 +44,13 @@ jobs:
           fetch-depth: 0 # We need full history for version number
 
       - name: "Download artifacts"
-        uses: actions/download-artifact@v3
+        uses: actions/download-artifact@v4
         with:
           name: "Artifacts"
           path: "./build/artifacts/"
 
       - name: "Setup .NET SDK"
-        uses: actions/setup-dotnet@v3
+        uses: actions/setup-dotnet@v4
         with:
           dotnet-version: ${{ inputs.dotnet_version }}
 
diff --git a/.gitignore b/.gitignore
index c414d09..b5b4377 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,4 @@ build/temp/
 .vs/
 *.csproj.user
 *.DotSettings.user
+launchSettings.json
diff --git a/build/orchestrator/BuildSystem.csproj b/build/orchestrator/BuildSystem.csproj
index 560a707..a633649 100644
--- a/build/orchestrator/BuildSystem.csproj
+++ b/build/orchestrator/BuildSystem.csproj
@@ -11,7 +11,7 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Cake.Frosting.PleOps.Recipe" Version="1.0.1" />
+    <PackageReference Include="Cake.Frosting.PleOps.Recipe" Version="1.0.3" />
   </ItemGroup>
 
 </Project>
diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props
index cba8860..70f56bc 100644
--- a/src/Directory.Packages.props
+++ b/src/Directory.Packages.props
@@ -1,14 +1,14 @@
 <Project>
   <!-- Centralize dependency management -->
   <ItemGroup>
-    <PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
-    <PackageVersion Include="Yarhl" Version="4.0.0-preview.283" />
-    <PackageVersion Include="YamlDotNet" Version="13.7.1" />
-    <PackageVersion Include="FluentAssertions" Version="6.12.0" />
-    <PackageVersion Include="nunit" Version="4.0.1" />
-    <PackageVersion Include="NUnit3TestAdapter" Version="4.5.0" />
-    <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
-    <PackageVersion Include="coverlet.collector" Version="6.0.0" />
-    <PackageVersion Include="SonarAnalyzer.CSharp" Version="9.15.0.81779" />
+    <PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1" />
+    <PackageVersion Include="Yarhl" Version="4.0.0" />
+    <PackageVersion Include="YamlDotNet" Version="16.1.0" />
+    <PackageVersion Include="FluentAssertions" Version="6.12.1" />
+    <PackageVersion Include="nunit" Version="4.2.2" />
+    <PackageVersion Include="NUnit3TestAdapter" Version="4.6.0" />
+    <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
+    <PackageVersion Include="coverlet.collector" Version="6.0.2" />
+    <PackageVersion Include="SonarAnalyzer.CSharp" Version="9.32.0.97167" />
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/src/Lemon/Containers/Converters/BinaryExeFs2NodeContainer.cs b/src/Lemon/Containers/Converters/BinaryExeFs2NodeContainer.cs
index 465a3f4..98d125c 100644
--- a/src/Lemon/Containers/Converters/BinaryExeFs2NodeContainer.cs
+++ b/src/Lemon/Containers/Converters/BinaryExeFs2NodeContainer.cs
@@ -88,7 +88,7 @@ public NodeContainerFormat Convert(BinaryFormat source)
                 byte[] actual = ComputeHash(container.Root.Children[i].Stream);
 
                 if (!expected.SequenceEqual(actual)) {
-                    logger.LogWarning("Wrong hash for child {name}", container.Root.Children[i].Name);
+                    logger.LogWarning("Wrong hash for child {Name}", container.Root.Children[i].Name);
                 }
             }
 
@@ -168,15 +168,15 @@ private static byte[] ComputeHash(DataStream stream)
                 // Read the file in blocks of 64 KB (small enough for the SOH).
                 stream.Position = 0;
                 int offset = 0;
+                int read;
                 byte[] buffer = new byte[1024 * 64];
                 while (offset + buffer.Length < stream.Length) {
-                    stream.Read(buffer, 0, buffer.Length);
-                    offset += sha.TransformBlock(buffer, 0, buffer.Length, buffer, 0);
+                    read = stream.Read(buffer, 0, buffer.Length);
+                    offset += sha.TransformBlock(buffer, 0, read, buffer, 0);
                 }
 
-                int finalSize = (int)(stream.Length - offset);
-                stream.Read(buffer, 0, finalSize);
-                sha.TransformFinalBlock(buffer, 0, finalSize);
+                read = stream.Read(buffer);
+                sha.TransformFinalBlock(buffer, 0, read);
 
                 hash = sha.Hash;
             }
diff --git a/src/Lemon/Containers/Converters/BinaryIvfc2NodeContainer.cs b/src/Lemon/Containers/Converters/BinaryIvfc2NodeContainer.cs
index d0b3762..c41555b 100644
--- a/src/Lemon/Containers/Converters/BinaryIvfc2NodeContainer.cs
+++ b/src/Lemon/Containers/Converters/BinaryIvfc2NodeContainer.cs
@@ -84,7 +84,7 @@ public NodeContainerFormat Convert(BinaryFormat source)
 
             uint version = reader.ReadUInt32();
             if (version != SupportedVersion) {
-                logger.LogWarning("Unsupported version: {actual}, expecting {supported}.", version, SupportedVersion);
+                logger.LogWarning("Unsupported version: {Actual}, expecting {Supported}.", version, SupportedVersion);
             }
 
             // Level 0, 1 and 2 only contain SHA-256 hashes. We can skip
diff --git a/src/Lemon/Containers/Converters/Ivfc/FileSystemWriter.cs b/src/Lemon/Containers/Converters/Ivfc/FileSystemWriter.cs
index 8dcbaa6..21ce4cf 100644
--- a/src/Lemon/Containers/Converters/Ivfc/FileSystemWriter.cs
+++ b/src/Lemon/Containers/Converters/Ivfc/FileSystemWriter.cs
@@ -126,7 +126,7 @@ private void Analyze()
                     info.Directories++;
                     info.DirNamesLength += NameEncoding.GetByteCount(node.Name).Pad(0x04);
                 } else if (node.Stream == null) {
-                    logger.LogError("Node '{path}' is not a folder or a binary file.", node.Path);
+                    logger.LogError("Node '{Path}' is not a folder or a binary file.", node.Path);
                 } else {
                     info.Files++;
                     info.FileNamesLength += NameEncoding.GetByteCount(node.Name).Pad(0x04);
diff --git a/src/Lemon/Containers/Converters/Ncch2Binary.cs b/src/Lemon/Containers/Converters/Ncch2Binary.cs
index c195493..be7f177 100644
--- a/src/Lemon/Containers/Converters/Ncch2Binary.cs
+++ b/src/Lemon/Containers/Converters/Ncch2Binary.cs
@@ -36,9 +36,7 @@ namespace SceneGate.Lemon.Containers.Converters
     /// </summary>
     /// <remarks>
     /// <p>This converter expects to have a node with the following binary
-    /// children: header_data/partition_id, header_data/maker_code
-    /// header_data/version, header_data/program_id, header_data/product_code,
-    /// header_data/flag_(0 through 7),
+    /// children:
     /// extended_header (optional), access_descriptor (optional), sdk_info.txt (optional),
     /// logo.bin (optional), system (optional), rom (optional).</p>
     /// </remarks>
@@ -147,10 +145,10 @@ public BinaryFormat Convert(Ncch source)
             return binary;
         }
 
-        private void WriteFile(DataWriter writer, Node file, bool isRequired = true)
+        private static void WriteFile(DataWriter writer, Node file, bool isRequired = true)
         {
             if (file == null && isRequired) {
-                throw new System.IO.FileNotFoundException("Missing NCCH file");
+                throw new FileNotFoundException("Missing NCCH file");
             } else if (file == null) {
                 return;
             }
@@ -162,7 +160,11 @@ private void WriteFile(DataWriter writer, Node file, bool isRequired = true)
             file.Stream.WriteTo(writer.Stream);
         }
 
-        private void WriteOffsetSizeAndData(DataWriter writer, Node file, int hashRegion = 0, bool hasHashRegion = false)
+        private static void WriteOffsetSizeAndData(
+            DataWriter writer,
+            Node file,
+            int hashRegion = 0,
+            bool hasHashRegion = false)
         {
             if (file != null) {
                 long position = writer.Stream.Position;
@@ -189,7 +191,11 @@ private void WriteOffsetSizeAndData(DataWriter writer, Node file, int hashRegion
             }
         }
 
-        private void WriteSHA256(DataWriter writer, Node file, int hashRegion = 0, bool hasHashRegion = false)
+        private static void WriteSHA256(
+            DataWriter writer,
+            Node file,
+            int hashRegion = 0,
+            bool hasHashRegion = false)
         {
             if (file is null) {
                 writer.Write(new byte[0x20]);
@@ -205,7 +211,10 @@ private void WriteSHA256(DataWriter writer, Node file, int hashRegion = 0, bool
                     int hashSize = hashRegion * 0x200;
                     byte[] buffer = new byte[hashSize];
                     file.Stream.Position = 0;
-                    file.Stream.Read(buffer, 0, hashSize);
+                    int read = file.Stream.Read(buffer, 0, hashSize);
+                    if (read != hashSize) {
+                        throw new EndOfStreamException();
+                    }
 
                     writer.Write(sha256.ComputeHash(buffer));
                 } else {
diff --git a/src/Lemon/Containers/Converters/NodeContainer2BinaryCia.cs b/src/Lemon/Containers/Converters/NodeContainer2BinaryCia.cs
index 38abc23..773cd05 100644
--- a/src/Lemon/Containers/Converters/NodeContainer2BinaryCia.cs
+++ b/src/Lemon/Containers/Converters/NodeContainer2BinaryCia.cs
@@ -106,7 +106,7 @@ public BinaryFormat Convert(NodeContainerFormat source)
             return binary;
         }
 
-        private void WriteHeader(DataWriter writer, Node root)
+        private static void WriteHeader(DataWriter writer, Node root)
         {
             writer.Write(HeaderSize);
             writer.Write(CiaType);
@@ -120,7 +120,7 @@ private void WriteHeader(DataWriter writer, Node root)
             writer.WritePadding(0x00, BlockSize);
         }
 
-        private void WriteFile(DataWriter writer, Node file, bool isRequired = true)
+        private static void WriteFile(DataWriter writer, Node file, bool isRequired = true)
         {
             if (file == null && isRequired) {
                 throw new FileNotFoundException("Missing CIA file");
@@ -138,7 +138,7 @@ private void WriteFile(DataWriter writer, Node file, bool isRequired = true)
             writer.WritePadding(0x00, BlockSize);
         }
 
-        private void UpdateTitleMetadata(TitleMetadata title, Node content)
+        private static void UpdateTitleMetadata(TitleMetadata title, Node content)
         {
             // Update size and HASH title chunks (CIA content children)
             // The hashes of the records and TMD will be updated when writing.
@@ -175,7 +175,7 @@ private static byte[] SHA256FromStream(DataStream stream)
             }
         }
 
-        private void WriteContent(DataWriter writer, Node content, TitleMetadata title)
+        private static void WriteContent(DataWriter writer, Node content, TitleMetadata title)
         {
             int contentBitset = 0;
             long contentSize = 0;
diff --git a/src/nuget.config b/src/nuget.config
index 402a95f..f3028dd 100644
--- a/src/nuget.config
+++ b/src/nuget.config
@@ -3,15 +3,10 @@
   <packageSources>
     <clear/>
     <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
-    <add key="SceneGate-Preview" value="https://pkgs.dev.azure.com/SceneGate/SceneGate/_packaging/SceneGate-Preview/nuget/v3/index.json" />
   </packageSources>
   <packageSourceMapping>
     <packageSource key="nuget.org">
       <package pattern="*" />
     </packageSource>
-    <packageSource key="SceneGate-Preview">
-      <package pattern="Yarhl*" />
-      <package pattern="Texim" />
-    </packageSource>
   </packageSourceMapping>
 </configuration>