This commit is contained in:
2026-05-06 12:19:31 +03:00
parent 17266730fc
commit 89cb5a10da
34 changed files with 198 additions and 226 deletions
+2 -2
View File
@@ -210,8 +210,8 @@ try
logger.LogInformation("Environment: {Environment}", app.Environment.EnvironmentName);
// Log all environment variables and configuration settings at startup
// Can be controlled via appsettings: "Logging:LogEnvironmentOnStartup": true
var logEnvironmentOnStartup = app.Configuration.GetValue<bool>("Logging:LogEnvironmentOnStartup", defaultValue: true);
// Can be controlled via appsettings: "LogEnvironmentOnStartup": true
var logEnvironmentOnStartup = app.Configuration.GetValue<bool>("LogEnvironmentOnStartup", defaultValue: true);
if (logEnvironmentOnStartup)
{
LogEnvironmentSettings(logger, app.Configuration, app.Environment);
+2 -2
View File
@@ -36,9 +36,9 @@
"Microsoft.AspNetCore.Routing": "Warning",
"System.Net.Http.HttpClient": "Warning",
"Api": "Debug"
},
"LogEnvironmentOnStartup": true
}
},
"LogEnvironmentOnStartup": true,
"KeyVault": {
"VaultUri": "",
"Enabled": false
+1 -1
View File
@@ -58,7 +58,6 @@
]
},
"Logging": {
"LogEnvironmentOnStartup": true,
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
@@ -68,6 +67,7 @@
"Api": "Information"
}
},
"LogEnvironmentOnStartup": true,
"AllowedHosts": "*",
"KeyVault": {
"VaultUri": "",
@@ -1,4 +1,4 @@
namespace Api.Services.Contracts;
namespace Api.Clients.Ai.Contracts;
public interface IMatcherAiClient
{
@@ -1,7 +1,7 @@
using System.Security.Cryptography;
using System.Text;
namespace Api.Services;
namespace Api.Clients.Ai;
public static class HashHelper
{
@@ -2,11 +2,12 @@ using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using Api.Services.Contracts;
using Api.Settings;
using Api.Clients.Ai.Contracts;
using Api.Data.Repositories.Contracts;
using Api.Models.Settings;
using Microsoft.Extensions.Options;
namespace Api.Services;
namespace Api.Clients.Ai;
public sealed class MatcherAiClient : IMatcherAiClient
{
@@ -1,7 +1,7 @@
using Api.Requests;
using Api.Responses;
using Api.Models.Requests;
using Api.Models.Responses;
namespace Api.Services.Contracts;
namespace Api.Clients.Api.Contracts;
public interface IRagApiClient
{
@@ -0,0 +1,30 @@
using Refit;
using Api.Models.Responses;
using Api.Models.Requests;
namespace Api.Clients.Api.Contracts;
[Headers("Accept: application/json")]
public interface IRefitRagApi
{
[Multipart]
[Post("/api/rag/documents")]
Task<RagIndexResponse> IndexDocumentAsync([AliasAs("file")] StreamPart file,
[AliasAs("documentType")] string documentType,
[AliasAs("title")] string title,
CancellationToken ct = default);
[Multipart]
[Post("/api/rag/documents")]
Task<RagIndexResponse> IndexDocumentWithTextAsync([AliasAs("text")] string text,
[AliasAs("documentType")] string documentType,
[AliasAs("title")] string title,
[AliasAs("sourceUrl")] string? sourceUrl = null,
CancellationToken ct = default);
[Get("/api/rag/documents/{documentId}")]
Task<RagDocumentDetails> GetDocumentAsync(string documentId, CancellationToken ct = default);
[Post("/api/rag/search")]
Task<RagSearchResponse> SearchAsync([Body] RagSearchRequest request, CancellationToken ct = default);
}
@@ -0,0 +1,48 @@
using System.Net;
using Refit;
using Microsoft.Extensions.Options;
using Api.Clients.Api.Contracts;
using Api.Models.Responses;
using Api.Models.Settings;
using Api.Models.Requests;
namespace Api.Clients.Api;
public sealed class RagApiClient : IRagApiClient
{
private readonly IRefitRagApi _refit;
public RagApiClient(IRefitRagApi refit, IOptions<RagApiSettings> options)
{
_refit = refit;
}
public async Task<RagIndexResponse> IndexCvPdfAsync(IFormFile file, CancellationToken ct)
{
await using var stream = file.OpenReadStream();
var part = new StreamPart(stream, file.FileName, "application/pdf");
return await _refit.IndexDocumentAsync(part, "cv", file.FileName, ct);
}
public async Task<RagIndexResponse> IndexJobTextAsync(string text, string? url, string? title, CancellationToken ct)
{
return await _refit.IndexDocumentWithTextAsync(text, "job", title ?? "Job description", url, ct);
}
public async Task<RagDocumentDetails?> GetDocumentAsync(string documentId, CancellationToken ct)
{
try
{
return await _refit.GetDocumentAsync(documentId, ct);
}
catch (ApiException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
{
return null;
}
}
public async Task<RagSearchResponse> SearchAsync(RagSearchRequest request, CancellationToken ct)
{
return await _refit.SearchAsync(request, ct);
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
using Api.Requests;
using Api.Models.Requests;
using Api.Services.Contracts;
using Microsoft.AspNetCore.Mvc;
@@ -1,6 +1,6 @@
using Api.Responses;
using Api.Models.Responses;
namespace Api.Services.Contracts;
namespace Api.Data.Repositories.Contracts;
public interface IMatcherRepository
{
@@ -1,11 +1,11 @@
using System.Text.Json;
using Api.Data;
using Api.Data.Entities;
using Api.Responses;
using Api.Services.Contracts;
using Api.Data.Repositories.Contracts;
using Api.Models.Responses;
using Microsoft.EntityFrameworkCore;
namespace Api.Services;
namespace Api.Data.Repositories;
public sealed class EfMatcherRepository : IMatcherRepository
{
-25
View File
@@ -1,25 +0,0 @@
IF OBJECT_ID('dbo.CvMatchResults', 'U') IS NULL
BEGIN
CREATE TABLE dbo.CvMatchResults (
Id NVARCHAR(64) NOT NULL CONSTRAINT PK_CvMatchResults PRIMARY KEY,
CvDocumentId NVARCHAR(64) NOT NULL,
JobDocumentId NVARCHAR(64) NOT NULL,
ResultJson NVARCHAR(MAX) NOT NULL,
Score INT NOT NULL,
CreatedAt DATETIME2 NOT NULL CONSTRAINT DF_CvMatchResults_CreatedAt DEFAULT SYSUTCDATETIME()
);
CREATE UNIQUE INDEX UX_CvMatchResults_CvJob ON dbo.CvMatchResults(CvDocumentId, JobDocumentId);
END
GO
IF OBJECT_ID('dbo.CvMatcherChatCache', 'U') IS NULL
BEGIN
CREATE TABLE dbo.CvMatcherChatCache (
CacheKey NVARCHAR(64) NOT NULL CONSTRAINT PK_CvMatcherChatCache PRIMARY KEY,
Model NVARCHAR(120) NOT NULL,
Temperature DECIMAL(4,2) NOT NULL,
ResponseText NVARCHAR(MAX) NOT NULL,
CreatedAt DATETIME2 NOT NULL CONSTRAINT DF_CvMatcherChatCache_CreatedAt DEFAULT SYSUTCDATETIME()
);
END
GO
@@ -1,4 +1,4 @@
namespace Api.Requests
namespace Api.Models.Requests
{
public sealed class FindJobsRequest
{
@@ -1,4 +1,4 @@
namespace Api.Requests
namespace Api.Models.Requests
{
public sealed class MatchJobRequest
{
@@ -1,4 +1,4 @@
namespace Api.Requests
namespace Api.Models.Requests
{
public sealed class RagSearchRequest
{
@@ -1,4 +1,4 @@
namespace Api.Responses
namespace Api.Models.Responses
{
public sealed class CvUploadResponse
{
@@ -1,4 +1,4 @@
namespace Api.Responses
namespace Api.Models.Responses
{
public sealed class FindJobsResponse
{
@@ -1,4 +1,4 @@
namespace Api.Responses
namespace Api.Models.Responses
{
public sealed class JobMatchResponse
{
@@ -1,4 +1,4 @@
namespace Api.Responses
namespace Api.Models.Responses
{
public sealed class RagIndexResponse
{
@@ -1,4 +1,4 @@
namespace Api.Responses
namespace Api.Models.Responses
{
public sealed class RagSearchResponse
{
@@ -1,4 +1,4 @@
namespace Api.Settings;
namespace Api.Models.Settings;
public sealed class RagApiSettings
{
+23 -4
View File
@@ -2,11 +2,18 @@ using Azure.Identity;
using Api.Data;
using Api.Services;
using Api.Services.Contracts;
using Api.Settings;
using Microsoft.AspNetCore.Diagnostics;
using Serilog;
using System.Reflection;
using Microsoft.EntityFrameworkCore;
using Refit;
using Api.Data.Repositories;
using Api.Data.Repositories.Contracts;
using Api.Clients.Api;
using Api.Clients.Api.Contracts;
using Api.Clients.Ai;
using Api.Clients.Ai.Contracts;
using Api.Models.Settings;
DotNetEnv.Env.Load();
@@ -68,7 +75,19 @@ try
builder.Services.Configure<MatcherSettings>(builder.Configuration.GetSection("Matcher"));
builder.Services.Configure<SmtpSettings>(builder.Configuration.GetSection("Smtp"));
builder.Services.AddHttpClient<IRagApiClient, RagApiClient>();
// Register Refit client for the external RAG API and a thin wrapper that implements IRagApiClient
builder.Services.AddRefitClient<IRefitRagApi>()
.ConfigureHttpClient((sp, c) =>
{
var settings = sp.GetRequiredService<Microsoft.Extensions.Options.IOptions<RagApiSettings>>().Value;
c.BaseAddress = new Uri(settings.BaseUrl.TrimEnd('/') + "/");
if (!string.IsNullOrWhiteSpace(settings.InternalApiKey))
{
c.DefaultRequestHeaders.Add("X-Internal-Api-Key", settings.InternalApiKey);
}
});
builder.Services.AddScoped<IRagApiClient, RagApiClient>();
builder.Services.AddHttpClient<IMatcherAiClient, MatcherAiClient>();
builder.Services.AddHttpClient<IJobTextExtractor, JobTextExtractor>();
builder.Services.AddDbContext<CvMatcherDbContext>(options =>
@@ -89,8 +108,8 @@ try
logger.LogInformation("Environment: {Environment}", app.Environment.EnvironmentName);
// Log all environment variables and configuration settings at startup
// Can be controlled via appsettings: "Logging:LogEnvironmentOnStartup": true
var logEnvironmentOnStartup = app.Configuration.GetValue<bool>("Logging:LogEnvironmentOnStartup", defaultValue: true);
// Can be controlled via appsettings: "LogEnvironmentOnStartup": true
var logEnvironmentOnStartup = app.Configuration.GetValue<bool>("LogEnvironmentOnStartup", defaultValue: true);
if (logEnvironmentOnStartup)
{
LogEnvironmentSettings(logger, app.Configuration, app.Environment);
@@ -1,5 +1,5 @@
using Api.Requests;
using Api.Responses;
using Api.Models.Requests;
using Api.Models.Responses;
namespace Api.Services.Contracts;
+6 -3
View File
@@ -1,8 +1,11 @@
using System.Text.Json;
using Api.Requests;
using Api.Responses;
using Api.Clients.Ai.Contracts;
using Api.Clients.Api.Contracts;
using Api.Data.Repositories.Contracts;
using Api.Models.Requests;
using Api.Models.Responses;
using Api.Models.Settings;
using Api.Services.Contracts;
using Api.Settings;
using Microsoft.Extensions.Options;
namespace Api.Services;
+1 -1
View File
@@ -1,5 +1,5 @@
using Api.Models.Settings;
using Api.Services.Contracts;
using Api.Settings;
using MailKit.Net.Smtp;
using MailKit.Security;
using Microsoft.Extensions.Options;
+1 -1
View File
@@ -1,7 +1,7 @@
using System.Net;
using System.Text.RegularExpressions;
using Api.Models.Settings;
using Api.Services.Contracts;
using Api.Settings;
using Microsoft.Extensions.Options;
namespace Api.Services;
-80
View File
@@ -1,80 +0,0 @@
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using Api.Requests;
using Api.Responses;
using Api.Services.Contracts;
using Api.Settings;
using Microsoft.Extensions.Options;
namespace Api.Services;
public sealed class RagApiClient : IRagApiClient
{
private readonly HttpClient _http;
private readonly RagApiSettings _settings;
private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web);
public RagApiClient(HttpClient http, IOptions<RagApiSettings> options)
{
_http = http;
_settings = options.Value;
_http.BaseAddress = new Uri(_settings.BaseUrl.TrimEnd('/') + "/");
if (!string.IsNullOrWhiteSpace(_settings.InternalApiKey))
{
_http.DefaultRequestHeaders.Add("X-Internal-Api-Key", _settings.InternalApiKey);
}
}
public async Task<RagIndexResponse> IndexCvPdfAsync(IFormFile file, CancellationToken ct)
{
using var content = new MultipartFormDataContent();
await using var stream = file.OpenReadStream();
using var fileContent = new StreamContent(stream);
fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
content.Add(fileContent, "file", file.FileName);
content.Add(new StringContent("cv"), "documentType");
content.Add(new StringContent(file.FileName), "title");
using var response = await _http.PostAsync("api/rag/documents", content, ct);
return await ReadJsonAsync<RagIndexResponse>(response, ct);
}
public async Task<RagIndexResponse> IndexJobTextAsync(string text, string? url, string? title, CancellationToken ct)
{
using var content = new MultipartFormDataContent
{
{ new StringContent(text), "text" },
{ new StringContent("job"), "documentType" },
{ new StringContent(title ?? "Job description"), "title" }
};
if (!string.IsNullOrWhiteSpace(url)) content.Add(new StringContent(url), "sourceUrl");
using var response = await _http.PostAsync("api/rag/documents", content, ct);
return await ReadJsonAsync<RagIndexResponse>(response, ct);
}
public async Task<RagDocumentDetails?> GetDocumentAsync(string documentId, CancellationToken ct)
{
using var response = await _http.GetAsync($"api/rag/documents/{Uri.EscapeDataString(documentId)}", ct);
if (response.StatusCode == System.Net.HttpStatusCode.NotFound) return null;
return await ReadJsonAsync<RagDocumentDetails>(response, ct);
}
public async Task<RagSearchResponse> SearchAsync(RagSearchRequest request, CancellationToken ct)
{
using var response = await _http.PostAsync(
"api/rag/search",
new StringContent(JsonSerializer.Serialize(request, JsonOptions), Encoding.UTF8, "application/json"),
ct);
return await ReadJsonAsync<RagSearchResponse>(response, ct);
}
private static async Task<T> ReadJsonAsync<T>(HttpResponseMessage response, CancellationToken ct)
{
var json = await response.Content.ReadAsStringAsync(ct);
if (!response.IsSuccessStatusCode)
{
throw new InvalidOperationException($"RAG API failed: {(int)response.StatusCode} {json}");
}
return JsonSerializer.Deserialize<T>(json, JsonOptions) ?? throw new InvalidOperationException("RAG API returned invalid JSON.");
}
}
+1 -1
View File
@@ -58,7 +58,6 @@
]
},
"Logging": {
"LogEnvironmentOnStartup": true,
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
@@ -68,6 +67,7 @@
"Api": "Information"
}
},
"LogEnvironmentOnStartup": true,
"AllowedHosts": "*",
"KeyVault": {
"VaultUri": "",
+4 -8
View File
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
@@ -59,8 +59,8 @@
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.5.1" />
<PackageReference Include="Azure.Identity" Version="1.21.0" />
<PackageReference Include="DotNetEnv" Version="3.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.0">
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.7">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
@@ -70,10 +70,6 @@
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
<PackageReference Include="Serilog.Sinks.Email" Version="4.2.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.7" />
</ItemGroup>
<ItemGroup>
<None Update="Database/schema.sql">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<PackageReference Include="Refit.HttpClientFactory" Version="10.1.6" />
</ItemGroup>
</Project>
-63
View File
@@ -1,63 +0,0 @@
IF OBJECT_ID('dbo.RagChunks', 'U') IS NULL
BEGIN
CREATE TABLE dbo.RagChunks (
Id NVARCHAR(64) NOT NULL CONSTRAINT PK_RagChunks PRIMARY KEY,
DocumentId NVARCHAR(64) NOT NULL,
ChunkIndex INT NOT NULL,
Text NVARCHAR(MAX) NOT NULL,
Embedding VARBINARY(MAX) NOT NULL
);
END
GO
IF OBJECT_ID('dbo.RagDocuments', 'U') IS NULL
BEGIN
CREATE TABLE dbo.RagDocuments (
Id NVARCHAR(64) NOT NULL CONSTRAINT PK_RagDocuments PRIMARY KEY,
DocumentType NVARCHAR(80) NOT NULL,
Title NVARCHAR(300) NOT NULL,
SourceUrl NVARCHAR(1200) NULL,
RawText NVARCHAR(MAX) NOT NULL,
TextHash NVARCHAR(64) NOT NULL,
TypeConfidence FLOAT NOT NULL,
MetadataJson NVARCHAR(MAX) NOT NULL CONSTRAINT DF_RagDocuments_MetadataJson DEFAULT '{}',
CreatedAt DATETIME2 NOT NULL CONSTRAINT DF_RagDocuments_CreatedAt DEFAULT SYSUTCDATETIME()
);
CREATE INDEX IX_RagDocuments_TextHash ON dbo.RagDocuments(TextHash);
CREATE INDEX IX_RagDocuments_DocumentType ON dbo.RagDocuments(DocumentType);
END
GO
IF NOT EXISTS (SELECT 1 FROM sys.foreign_keys WHERE name = 'FK_RagChunks_RagDocuments')
BEGIN
ALTER TABLE dbo.RagChunks
ADD CONSTRAINT FK_RagChunks_RagDocuments FOREIGN KEY (DocumentId) REFERENCES dbo.RagDocuments(Id) ON DELETE CASCADE;
END
GO
IF OBJECT_ID('dbo.RagEmbeddingCache', 'U') IS NULL
BEGIN
CREATE TABLE dbo.RagEmbeddingCache (
CacheKey NVARCHAR(64) NOT NULL CONSTRAINT PK_RagEmbeddingCache PRIMARY KEY,
Model NVARCHAR(120) NOT NULL,
TextHash NVARCHAR(64) NOT NULL,
Vector VARBINARY(MAX) NOT NULL,
CreatedAt DATETIME2 NOT NULL CONSTRAINT DF_RagEmbeddingCache_CreatedAt DEFAULT SYSUTCDATETIME()
);
CREATE INDEX IX_RagEmbeddingCache_TextHash ON dbo.RagEmbeddingCache(TextHash);
END
GO
IF OBJECT_ID('dbo.RagChatCompletionCache', 'U') IS NULL
BEGIN
CREATE TABLE dbo.RagChatCompletionCache (
CacheKey NVARCHAR(64) NOT NULL CONSTRAINT PK_RagChatCompletionCache PRIMARY KEY,
Model NVARCHAR(120) NOT NULL,
Temperature DECIMAL(4,2) NOT NULL,
ResponseText NVARCHAR(MAX) NOT NULL,
CreatedAt DATETIME2 NOT NULL CONSTRAINT DF_RagChatCompletionCache_CreatedAt DEFAULT SYSUTCDATETIME()
);
END
GO
+2 -2
View File
@@ -89,8 +89,8 @@ try
logger.LogInformation("Environment: {Environment}", app.Environment.EnvironmentName);
// Log all environment variables and configuration settings at startup
// Can be controlled via appsettings: "Logging:LogEnvironmentOnStartup": true
var logEnvironmentOnStartup = app.Configuration.GetValue<bool>("Logging:LogEnvironmentOnStartup", defaultValue: true);
// Can be controlled via appsettings: "LogEnvironmentOnStartup": true
var logEnvironmentOnStartup = app.Configuration.GetValue<bool>("LogEnvironmentOnStartup", defaultValue: true);
if (logEnvironmentOnStartup)
{
LogEnvironmentSettings(logger, app.Configuration, app.Environment);
+1 -1
View File
@@ -58,7 +58,6 @@
]
},
"Logging": {
"LogEnvironmentOnStartup": true,
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
@@ -68,6 +67,7 @@
"Api": "Information"
}
},
"LogEnvironmentOnStartup": true,
"AllowedHosts": "*",
"KeyVault": {
"VaultUri": "",
+50 -7
View File
@@ -6,13 +6,61 @@
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<RootNamespace>Api</RootNamespace>
</PropertyGroup>
<ItemGroup>
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\cs\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\de\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\es\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\fr\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\it\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\ja\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\ko\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\Microsoft.Build.Locator.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.exe" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.exe.config" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\Microsoft.IO.Redist.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\Newtonsoft.Json.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\pl\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\pt-BR\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\ru\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\System.Buffers.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\System.Collections.Immutable.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\System.CommandLine.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\System.Memory.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\System.Numerics.Vectors.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\System.Runtime.CompilerServices.Unsafe.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\System.Threading.Tasks.Extensions.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\tr\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\zh-Hans\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-net472\zh-Hant\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\cs\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\de\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\es\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\fr\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\it\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\ja\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\ko\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\Microsoft.Build.Locator.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.deps.json" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.dll.config" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.runtimeconfig.json" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\Newtonsoft.Json.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\pl\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\pt-BR\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\ru\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\System.Collections.Immutable.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\System.CommandLine.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\tr\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\zh-Hans\System.CommandLine.resources.dll" />
<Content Remove="C:\Users\Gelu\.nuget\packages\microsoft.codeanalysis.workspaces.msbuild\4.14.0\contentFiles\any\any\BuildHost-netcore\zh-Hant\System.CommandLine.resources.dll" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.5.1" />
<PackageReference Include="Azure.Identity" Version="1.21.0" />
<PackageReference Include="DotNetEnv" Version="3.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.0">
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.7">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
@@ -23,9 +71,4 @@
<PackageReference Include="Serilog.Sinks.Email" Version="4.2.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.7" />
</ItemGroup>
<ItemGroup>
<None Update="Database/schema.sql">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>