aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar vman <public@vaughnnugent.com>2022-11-30 14:59:18 -0500
committerLibravatar vman <public@vaughnnugent.com>2022-11-30 14:59:18 -0500
commitf13193aa928f099c8152653570d2839b46b8f1ee (patch)
treebe2394edec528472258c0da7d354bbb8ad9881e4
parente4ce3ae25802471bea0ea99698fbb3f6ffdf7953 (diff)
Project cleanup + analyzer updates
-rw-r--r--VNLib.Plugins.Essentials.Accounts.Admin/VNLib.Plugins.Essentials.Accounts.Admin.csproj11
-rw-r--r--VNLib.Plugins.Essentials.Accounts.Registration/src/Endpoints/RegistrationEntpoint.cs2
-rw-r--r--VNLib.Plugins.Essentials.Accounts.Registration/src/RegistrationContext.cs (renamed from VNLib.Plugins.Essentials.Accounts.Registration/src/TokenRevocation/RevocationContext.cs)7
-rw-r--r--VNLib.Plugins.Essentials.Accounts.Registration/src/RegistrationEntryPoint.cs5
-rw-r--r--VNLib.Plugins.Essentials.Accounts.Registration/src/TokenRevocation/RevokedTokenStore.cs6
-rw-r--r--VNLib.Plugins.Essentials.Accounts.Registration/src/VNLib.Plugins.Essentials.Accounts.Registration.csproj20
-rw-r--r--VNLib.Plugins.Essentials.Accounts/MFA/MFAConfig.cs4
-rw-r--r--VNLib.Plugins.Essentials.Accounts/MFA/UserMFAExtensions.cs16
-rw-r--r--VNLib.Plugins.Essentials.Accounts/VNLib.Plugins.Essentials.Accounts.csproj15
-rw-r--r--VNLib.Plugins.Essentials.Content.Routing/PageRouterEntry.cs2
-rw-r--r--VNLib.Plugins.Essentials.Content.Routing/VNLib.Plugins.Essentials.Content.Routing.csproj12
-rw-r--r--VNLib.Plugins.Essentials.SocialOauth/ClientAccessTokenState.cs4
-rw-r--r--VNLib.Plugins.Essentials.SocialOauth/Endpoints/GitHubOauth.cs14
-rw-r--r--VNLib.Plugins.Essentials.SocialOauth/SocialOauthBase.cs4
-rw-r--r--VNLib.Plugins.Essentials.SocialOauth/VNLib.Plugins.Essentials.SocialOauth.csproj6
15 files changed, 66 insertions, 62 deletions
diff --git a/VNLib.Plugins.Essentials.Accounts.Admin/VNLib.Plugins.Essentials.Accounts.Admin.csproj b/VNLib.Plugins.Essentials.Accounts.Admin/VNLib.Plugins.Essentials.Accounts.Admin.csproj
index 6dbd219..00afb08 100644
--- a/VNLib.Plugins.Essentials.Accounts.Admin/VNLib.Plugins.Essentials.Accounts.Admin.csproj
+++ b/VNLib.Plugins.Essentials.Accounts.Admin/VNLib.Plugins.Essentials.Accounts.Admin.csproj
@@ -4,8 +4,15 @@
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
- <PlatformTarget>x64</PlatformTarget>
- <Platforms>AnyCPU;x64</Platforms>
+ <AnalysisLevel>latest-all</AnalysisLevel>
+ </PropertyGroup>
+
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
+ <Deterministic>False</Deterministic>
+ </PropertyGroup>
+
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
+ <Deterministic>False</Deterministic>
</PropertyGroup>
<ItemGroup>
diff --git a/VNLib.Plugins.Essentials.Accounts.Registration/src/Endpoints/RegistrationEntpoint.cs b/VNLib.Plugins.Essentials.Accounts.Registration/src/Endpoints/RegistrationEntpoint.cs
index 19d7ffa..1e983cb 100644
--- a/VNLib.Plugins.Essentials.Accounts.Registration/src/Endpoints/RegistrationEntpoint.cs
+++ b/VNLib.Plugins.Essentials.Accounts.Registration/src/Endpoints/RegistrationEntpoint.cs
@@ -102,7 +102,7 @@ namespace VNLib.Plugins.Essentials.Accounts.Registration.Endpoints
_ = ts.Result ?? throw new KeyNotFoundException("Missing required key 'reg_sig_key' in 'registration' configuration");
return Convert.FromBase64String(ts.Result);
- });
+ }, TaskScheduler.Default);
//Register timeout for cleanup
_ = plugin.ScheduleInterval(this, TimeSpan.FromSeconds(60));
diff --git a/VNLib.Plugins.Essentials.Accounts.Registration/src/TokenRevocation/RevocationContext.cs b/VNLib.Plugins.Essentials.Accounts.Registration/src/RegistrationContext.cs
index 4ff64b9..611e30e 100644
--- a/VNLib.Plugins.Essentials.Accounts.Registration/src/TokenRevocation/RevocationContext.cs
+++ b/VNLib.Plugins.Essentials.Accounts.Registration/src/RegistrationContext.cs
@@ -25,14 +25,15 @@
using Microsoft.EntityFrameworkCore;
using VNLib.Plugins.Extensions.Data;
+using VNLib.Plugins.Essentials.Accounts.Registration.TokenRevocation;
-namespace VNLib.Plugins.Essentials.Accounts.Registration.TokenRevocation
+namespace VNLib.Plugins.Essentials.Accounts.Registration
{
- internal class RevocationContext : TransactionalDbContext
+ internal class RegistrationContext : TransactionalDbContext
{
public DbSet<RevokedToken> RevokedRegistrationTokens { get; set; }
- public RevocationContext(DbContextOptions options) : base(options)
+ public RegistrationContext(DbContextOptions options) : base(options)
{}
}
} \ No newline at end of file
diff --git a/VNLib.Plugins.Essentials.Accounts.Registration/src/RegistrationEntryPoint.cs b/VNLib.Plugins.Essentials.Accounts.Registration/src/RegistrationEntryPoint.cs
index 1851cf2..c24e7e0 100644
--- a/VNLib.Plugins.Essentials.Accounts.Registration/src/RegistrationEntryPoint.cs
+++ b/VNLib.Plugins.Essentials.Accounts.Registration/src/RegistrationEntryPoint.cs
@@ -25,6 +25,7 @@
using VNLib.Utils.Logging;
using VNLib.Plugins.Extensions.Loading;
+using VNLib.Plugins.Extensions.Loading.Sql;
using VNLib.Plugins.Extensions.Loading.Routing;
using VNLib.Plugins.Essentials.Accounts.Registration.Endpoints;
@@ -40,7 +41,7 @@ namespace VNLib.Plugins.Essentials.Accounts.Registration
{
//Route reg endpoint
this.Route<RegistrationEntpoint>();
-
+
Log.Information("Plugin loaded");
}
catch(KeyNotFoundException kne)
@@ -48,7 +49,7 @@ namespace VNLib.Plugins.Essentials.Accounts.Registration
Log.Error("Missing required configuration variables: {ex}", kne.Message);
}
}
-
+
protected override void OnUnLoad()
{
Log.Information("Plugin unloaded");
diff --git a/VNLib.Plugins.Essentials.Accounts.Registration/src/TokenRevocation/RevokedTokenStore.cs b/VNLib.Plugins.Essentials.Accounts.Registration/src/TokenRevocation/RevokedTokenStore.cs
index c9217be..89f4bd6 100644
--- a/VNLib.Plugins.Essentials.Accounts.Registration/src/TokenRevocation/RevokedTokenStore.cs
+++ b/VNLib.Plugins.Essentials.Accounts.Registration/src/TokenRevocation/RevokedTokenStore.cs
@@ -41,7 +41,7 @@ namespace VNLib.Plugins.Essentials.Accounts.Registration.TokenRevocation
public async Task<bool> IsRevokedAsync(string token, CancellationToken cancellation)
{
- await using RevocationContext context = new (Options);
+ await using RegistrationContext context = new (Options);
await context.OpenTransactionAsync(cancellation);
//Select any that match tokens
@@ -55,7 +55,7 @@ namespace VNLib.Plugins.Essentials.Accounts.Registration.TokenRevocation
public async Task RevokeAsync(string token, CancellationToken cancellation)
{
- await using RevocationContext context = new (Options);
+ await using RegistrationContext context = new (Options);
await context.OpenTransactionAsync(cancellation);
//Add to table
@@ -80,7 +80,7 @@ namespace VNLib.Plugins.Essentials.Accounts.Registration.TokenRevocation
{
DateTime expiredBefore = DateTime.UtcNow.Subtract(validFor);
- await using RevocationContext context = new (Options);
+ await using RegistrationContext context = new (Options);
await context.OpenTransactionAsync(cancellation);
//Select any that match tokens
diff --git a/VNLib.Plugins.Essentials.Accounts.Registration/src/VNLib.Plugins.Essentials.Accounts.Registration.csproj b/VNLib.Plugins.Essentials.Accounts.Registration/src/VNLib.Plugins.Essentials.Accounts.Registration.csproj
index 25699c0..5a8597f 100644
--- a/VNLib.Plugins.Essentials.Accounts.Registration/src/VNLib.Plugins.Essentials.Accounts.Registration.csproj
+++ b/VNLib.Plugins.Essentials.Accounts.Registration/src/VNLib.Plugins.Essentials.Accounts.Registration.csproj
@@ -4,39 +4,29 @@
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
- <PlatformTarget>x64</PlatformTarget>
<GenerateDocumentationFile>False</GenerateDocumentationFile>
<Title>VNLib.Plugins.Essentials.Accounts.Registration</Title>
<Authors>Vaughn Nugent</Authors>
<Copyright>Copyright © 2022 Vaughn Nugent</Copyright>
- <PackageProjectUrl>www.vaughnnugent.com/resources</PackageProjectUrl>
+ <PackageProjectUrl>https://www.vaughnnugent.com/resources</PackageProjectUrl>
<ProduceReferenceAssembly>False</ProduceReferenceAssembly>
<SignAssembly>False</SignAssembly>
<AssemblyVersion>1.0.0.1</AssemblyVersion>
<AssemblyName>Essentials.EmailRegistration</AssemblyName>
- <Platforms>AnyCPU;x64</Platforms>
+ <CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
</PropertyGroup>
<!-- Resolve nuget dll files and store them in the output dir -->
<PropertyGroup>
<!--Enable dynamic loading-->
<EnableDynamicLoading>true</EnableDynamicLoading>
+ <AnalysisLevel>latest-all</AnalysisLevel>
</PropertyGroup>
-
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
- <CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
- </PropertyGroup>
-
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
+ <Deterministic>False</Deterministic>
</PropertyGroup>
-
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
- <CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
- </PropertyGroup>
-
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
+ <Deterministic>False</Deterministic>
</PropertyGroup>
<ItemGroup>
diff --git a/VNLib.Plugins.Essentials.Accounts/MFA/MFAConfig.cs b/VNLib.Plugins.Essentials.Accounts/MFA/MFAConfig.cs
index 8e85e65..f04693e 100644
--- a/VNLib.Plugins.Essentials.Accounts/MFA/MFAConfig.cs
+++ b/VNLib.Plugins.Essentials.Accounts/MFA/MFAConfig.cs
@@ -34,9 +34,9 @@ namespace VNLib.Plugins.Essentials.Accounts.MFA
{
internal class MFAConfig
{
- public byte[]? MFASecret { get; set; } = null;
+ public byte[]? MFASecret { get; set; }
- public bool TOTPEnabled { get; } = false;
+ public bool TOTPEnabled { get; }
public string? IssuerName { get; }
public TimeSpan TOTPPeriod { get; }
public HashAlg TOTPAlg { get; }
diff --git a/VNLib.Plugins.Essentials.Accounts/MFA/UserMFAExtensions.cs b/VNLib.Plugins.Essentials.Accounts/MFA/UserMFAExtensions.cs
index 3ebb6dd..6675a31 100644
--- a/VNLib.Plugins.Essentials.Accounts/MFA/UserMFAExtensions.cs
+++ b/VNLib.Plugins.Essentials.Accounts/MFA/UserMFAExtensions.cs
@@ -228,18 +228,12 @@ namespace VNLib.Plugins.Essentials.Accounts.MFA
MFAConfig mfa = new(conf);
//Recover secret from config and dangerous 'lazy load'
- _ = pbase.TryGetSecretAsync("mfa_secret").ContinueWith(t => {
-
- if(t.IsFaulted)
- {
- pbase.Log.Error(t.Exception!.InnerException, "Failed to load MFA signing secret");
- }
- else
- {
- mfa.MFASecret = t.Result != null ? Convert.FromBase64String(t.Result) : null;
- }
+ _ = pbase.DeferTask(async () =>
+ {
+ string? secret = await pbase.TryGetSecretAsync("mfa_secret");
+ mfa.MFASecret = secret != null ? Convert.FromBase64String(secret) : null;
});
-
+
return mfa;
}
//Return new lazy for
diff --git a/VNLib.Plugins.Essentials.Accounts/VNLib.Plugins.Essentials.Accounts.csproj b/VNLib.Plugins.Essentials.Accounts/VNLib.Plugins.Essentials.Accounts.csproj
index 56c09bc..719f8df 100644
--- a/VNLib.Plugins.Essentials.Accounts/VNLib.Plugins.Essentials.Accounts.csproj
+++ b/VNLib.Plugins.Essentials.Accounts/VNLib.Plugins.Essentials.Accounts.csproj
@@ -5,13 +5,11 @@
<RootNamespace>VNLib.Plugins.Essentials.Accounts</RootNamespace>
<Copyright>Copyright © 2022 Vaughn Nugent</Copyright>
<Authors>Vaughn Nugent</Authors>
- <AssemblyVersion>1.0.1.2</AssemblyVersion>
- <FileVersion>1.0.1.2</FileVersion>
<AssemblyName>Accounts</AssemblyName>
- <Platforms>AnyCPU;x64</Platforms>
+
<PackageId>VNLib.Plugins.Essentials.Accounts</PackageId>
- <Version>1.0.1</Version>
- <PackageProjectUrl>www.vaughnnugent.com/resources</PackageProjectUrl>
+ <Version>1.0.1.5</Version>
+ <PackageProjectUrl>https://www.vaughnnugent.com/resources</PackageProjectUrl>
</PropertyGroup>
@@ -20,6 +18,13 @@
<!--Enable dynamic loading-->
<EnableDynamicLoading>true</EnableDynamicLoading>
<Nullable>enable</Nullable>
+ <AnalysisLevel>latest-all</AnalysisLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
+ <Deterministic>False</Deterministic>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
+ <Deterministic>False</Deterministic>
</PropertyGroup>
<ItemGroup>
diff --git a/VNLib.Plugins.Essentials.Content.Routing/PageRouterEntry.cs b/VNLib.Plugins.Essentials.Content.Routing/PageRouterEntry.cs
index 4548f60..10b7075 100644
--- a/VNLib.Plugins.Essentials.Content.Routing/PageRouterEntry.cs
+++ b/VNLib.Plugins.Essentials.Content.Routing/PageRouterEntry.cs
@@ -58,7 +58,7 @@ namespace VNLib.Plugins.Essentials.Content.Routing
protected override void ProcessHostCommand(string cmd)
{
- if(cmd.Contains("reset"))
+ if(cmd.Contains("reset", StringComparison.OrdinalIgnoreCase))
{
PageRouter?.ResetRoutes();
Log.Information("Routing table reset");
diff --git a/VNLib.Plugins.Essentials.Content.Routing/VNLib.Plugins.Essentials.Content.Routing.csproj b/VNLib.Plugins.Essentials.Content.Routing/VNLib.Plugins.Essentials.Content.Routing.csproj
index 9d42c1e..c0188fa 100644
--- a/VNLib.Plugins.Essentials.Content.Routing/VNLib.Plugins.Essentials.Content.Routing.csproj
+++ b/VNLib.Plugins.Essentials.Content.Routing/VNLib.Plugins.Essentials.Content.Routing.csproj
@@ -3,18 +3,24 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Authors>Vaughn Nugent</Authors>
- <Version>1.0.0.1</Version>
+ <Version>1.0.1.1</Version>
<Copyright>Copyright © 2022 Vaughn Nugent</Copyright>
<PackageProjectUrl>https://www.vaughnnugent.com</PackageProjectUrl>
<AssemblyName>PageRouter</AssemblyName>
- <Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<!-- Resolve nuget dll files and store them in the output dir -->
<PropertyGroup>
<!--Enable dynamic loading-->
<EnableDynamicLoading>true</EnableDynamicLoading>
- <PlatformTarget>x64</PlatformTarget>
+ <Nullable>enable</Nullable>
+ <AnalysisLevel>latest-all</AnalysisLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
+ <Deterministic>False</Deterministic>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
+ <Deterministic>False</Deterministic>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ErrorProne.NET.CoreAnalyzers" Version="0.1.2">
diff --git a/VNLib.Plugins.Essentials.SocialOauth/ClientAccessTokenState.cs b/VNLib.Plugins.Essentials.SocialOauth/ClientAccessTokenState.cs
index 4d6f38d..e5de597 100644
--- a/VNLib.Plugins.Essentials.SocialOauth/ClientAccessTokenState.cs
+++ b/VNLib.Plugins.Essentials.SocialOauth/ClientAccessTokenState.cs
@@ -31,8 +31,6 @@ using VNLib.Utils.Memory;
using VNLib.Utils.Memory.Caching;
using VNLib.Plugins.Essentials.Accounts;
-#nullable enable
-
namespace VNLib.Plugins.Essentials.SocialOauth
{
public sealed class OAuthAccessState : IOAuthAccessState, ICacheable, INonce
@@ -68,7 +66,7 @@ namespace VNLib.Plugins.Essentials.SocialOauth
DateTime ICacheable.Expires { get; set; }
bool IEquatable<ICacheable>.Equals(ICacheable? other) => GetHashCode() == other?.GetHashCode();
- public override int GetHashCode() => Token!.GetHashCode();
+ public override int GetHashCode() => Token!.GetHashCode(StringComparison.Ordinal);
void ICacheable.Evicted()
{
Memory.UnsafeZeroMemory(Nonce);
diff --git a/VNLib.Plugins.Essentials.SocialOauth/Endpoints/GitHubOauth.cs b/VNLib.Plugins.Essentials.SocialOauth/Endpoints/GitHubOauth.cs
index 78b4b49..0b4fc0f 100644
--- a/VNLib.Plugins.Essentials.SocialOauth/Endpoints/GitHubOauth.cs
+++ b/VNLib.Plugins.Essentials.SocialOauth/Endpoints/GitHubOauth.cs
@@ -140,7 +140,7 @@ namespace VNLib.Plugins.Essentials.SocialOauth.Endpoints
if (!profResponse.IsSuccessful || profResponse.Data == null || profResponse.Data.ID < 100)
{
- Log.Debug("Client attempted a github login but GH responded with status code {code}", profResponse.StatusCode);
+ Log.Debug("Github login data attempt responded with status code {code}", profResponse.StatusCode);
return null;
}
@@ -173,9 +173,11 @@ namespace VNLib.Plugins.Essentials.SocialOauth.Endpoints
//Capture the first primary email address and make sure its verified
if (email.Primary && email.Verified)
{
- accountData ??= new();
- //store email on current profile
- accountData.EmailAddress = email.Email;
+ accountData = new()
+ {
+ //store email on current profile
+ EmailAddress = email.Email
+ };
goto Continue;
}
}
@@ -184,7 +186,7 @@ namespace VNLib.Plugins.Essentials.SocialOauth.Endpoints
}
else
{
- Log.Debug("Client attempted a github login but GH responded with status code {code}", getEmailResponse.StatusCode);
+ Log.Debug("Github account data request failed but GH responded with status code {code}", getEmailResponse.StatusCode);
return null;
}
Continue:
@@ -196,7 +198,7 @@ namespace VNLib.Plugins.Essentials.SocialOauth.Endpoints
RestResponse<GithubProfile> profResponse = await client.Resource.ExecuteAsync<GithubProfile>(request, cancellationToken);
if (!profResponse.IsSuccessful || profResponse.Data == null)
{
- Log.Debug("Client attempted a github login but GH responded with status code {code}", profResponse.StatusCode);
+ Log.Debug("Github account data request failed but GH responded with status code {code}", profResponse.StatusCode);
return null;
}
diff --git a/VNLib.Plugins.Essentials.SocialOauth/SocialOauthBase.cs b/VNLib.Plugins.Essentials.SocialOauth/SocialOauthBase.cs
index 72d0d1b..5728992 100644
--- a/VNLib.Plugins.Essentials.SocialOauth/SocialOauthBase.cs
+++ b/VNLib.Plugins.Essentials.SocialOauth/SocialOauthBase.cs
@@ -51,8 +51,6 @@ using VNLib.Plugins.Essentials.Extensions;
using VNLib.Plugins.Extensions.Validation;
using VNLib.Plugins.Essentials.SocialOauth.Validators;
-#nullable enable
-
namespace VNLib.Plugins.Essentials.SocialOauth
{
@@ -91,7 +89,7 @@ namespace VNLib.Plugins.Essentials.SocialOauth
private readonly IValidator<string> NonceValidator;
private readonly IValidator<AccountData> AccountDataValidator;
- public SocialOauthBase()
+ protected SocialOauthBase()
{
ClaimStore = new(StringComparer.OrdinalIgnoreCase);
AuthorizationStore = new(StringComparer.OrdinalIgnoreCase);
diff --git a/VNLib.Plugins.Essentials.SocialOauth/VNLib.Plugins.Essentials.SocialOauth.csproj b/VNLib.Plugins.Essentials.SocialOauth/VNLib.Plugins.Essentials.SocialOauth.csproj
index 0781d78..bbe9185 100644
--- a/VNLib.Plugins.Essentials.SocialOauth/VNLib.Plugins.Essentials.SocialOauth.csproj
+++ b/VNLib.Plugins.Essentials.SocialOauth/VNLib.Plugins.Essentials.SocialOauth.csproj
@@ -7,8 +7,7 @@
<Version>1.0.1.5</Version>
<Copyright>Copyright © 2022 Vaughn Nugent</Copyright>
<PackageProjectUrl>https://www.vaughnnugent.com/resources</PackageProjectUrl>
- <AssemblyName>SocialOauth</AssemblyName>
- <Platforms>AnyCPU;x64</Platforms>
+ <AssemblyName>SocialOauth</AssemblyName>
</PropertyGroup>
<ItemGroup>
@@ -28,6 +27,9 @@
<PropertyGroup>
<!--Enable dynamic loading-->
<EnableDynamicLoading>true</EnableDynamicLoading>
+ <Nullable>enable</Nullable>
+ <GenerateDocumentationFile>False</GenerateDocumentationFile>
+ <AnalysisLevel>latest-all</AnalysisLevel>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\VNLib\Essentials\VNLib.Plugins.Essentials.csproj" />