diff --git a/Apis/cv-search-data/cv-search-models.csproj b/Apis/cv-search-data/cv-search-models.csproj
deleted file mode 100644
index 310b3cf..0000000
--- a/Apis/cv-search-data/cv-search-models.csproj
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
- net10.0
- CvSearch.Models
- enable
- enable
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
diff --git a/Apis/cv-search-models/Migrations/20260522093356_AddJobSearchTables.Designer.cs b/Apis/cv-search-models/Migrations/20260522093356_AddJobSearchTables.Designer.cs
deleted file mode 100644
index 475bd9b..0000000
--- a/Apis/cv-search-models/Migrations/20260522093356_AddJobSearchTables.Designer.cs
+++ /dev/null
@@ -1,160 +0,0 @@
-//
-using System;
-using CvSearch.Models.Data;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-
-#nullable disable
-
-namespace CvSearch.Models.Migrations
-{
- [DbContext(typeof(CvSearchDbContext))]
- [Migration("20260522093356_AddJobSearchTables")]
- partial class AddJobSearchTables
- {
- ///
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder
- .HasDefaultSchema("cvSearch")
- .HasAnnotation("ProductVersion", "10.0.7")
- .HasAnnotation("Relational:MaxIdentifierLength", 128);
-
- SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
-
- modelBuilder.Entity("CvSearch.Models.Data.Entities.JobSearchResultEntity", b =>
- {
- b.Property("Id")
- .HasMaxLength(64)
- .HasColumnType("nvarchar(64)");
-
- b.Property("CreatedAt")
- .ValueGeneratedOnAdd()
- .HasColumnType("datetime2")
- .HasDefaultValueSql("SYSUTCDATETIME()");
-
- b.Property("JobText")
- .IsRequired()
- .HasColumnType("nvarchar(max)");
-
- b.Property("JobTitle")
- .IsRequired()
- .HasMaxLength(512)
- .HasColumnType("nvarchar(512)");
-
- b.Property("JobUrl")
- .IsRequired()
- .HasMaxLength(2048)
- .HasColumnType("nvarchar(2048)");
-
- b.Property("ProviderName")
- .IsRequired()
- .HasMaxLength(128)
- .HasColumnType("nvarchar(128)");
-
- b.Property("ResultJson")
- .IsRequired()
- .HasColumnType("nvarchar(max)");
-
- b.Property("Score")
- .HasColumnType("int");
-
- b.Property("SessionId")
- .IsRequired()
- .HasMaxLength(64)
- .HasColumnType("nvarchar(64)");
-
- b.HasKey("Id");
-
- b.HasIndex("SessionId");
-
- b.ToTable("JobSearchResults", "cvSearch");
- });
-
- modelBuilder.Entity("CvSearch.Models.Data.Entities.JobSearchSessionEntity", b =>
- {
- b.Property("Id")
- .HasMaxLength(64)
- .HasColumnType("nvarchar(64)");
-
- b.Property("CreatedAt")
- .ValueGeneratedOnAdd()
- .HasColumnType("datetime2")
- .HasDefaultValueSql("SYSUTCDATETIME()");
-
- b.Property("CvDocumentId")
- .IsRequired()
- .HasMaxLength(64)
- .HasColumnType("nvarchar(64)");
-
- b.Property("Email")
- .IsRequired()
- .HasMaxLength(256)
- .HasColumnType("nvarchar(256)");
-
- b.Property("Keywords")
- .IsRequired()
- .HasMaxLength(1000)
- .HasColumnType("nvarchar(1000)");
-
- b.Property("ProviderConfigJson")
- .HasColumnType("nvarchar(max)");
-
- b.Property("Status")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("nvarchar(32)");
-
- b.Property("TokenId")
- .IsRequired()
- .HasMaxLength(64)
- .HasColumnType("nvarchar(64)");
-
- b.HasKey("Id");
-
- b.HasIndex("Status");
-
- b.ToTable("JobSearchSessions", "cvSearch");
- });
-
- modelBuilder.Entity("CvSearch.Models.Data.Entities.JobSearchTokenEntity", b =>
- {
- b.Property("Id")
- .HasMaxLength(64)
- .HasColumnType("nvarchar(64)");
-
- b.Property("CreatedAt")
- .ValueGeneratedOnAdd()
- .HasColumnType("datetime2")
- .HasDefaultValueSql("SYSUTCDATETIME()");
-
- b.Property("CvDocumentId")
- .IsRequired()
- .HasMaxLength(64)
- .HasColumnType("nvarchar(64)");
-
- b.Property("Email")
- .IsRequired()
- .HasMaxLength(256)
- .HasColumnType("nvarchar(256)");
-
- b.Property("ExpiresAt")
- .HasColumnType("datetime2");
-
- b.Property("Used")
- .ValueGeneratedOnAdd()
- .HasColumnType("bit")
- .HasDefaultValue(false);
-
- b.HasKey("Id");
-
- b.ToTable("JobSearchTokens", "cvSearch");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/Apis/cv-search-models/Migrations/20260522093356_AddJobSearchTables.cs b/Apis/cv-search-models/Migrations/20260522093356_AddJobSearchTables.cs
deleted file mode 100644
index adbc233..0000000
--- a/Apis/cv-search-models/Migrations/20260522093356_AddJobSearchTables.cs
+++ /dev/null
@@ -1,102 +0,0 @@
-using System;
-using Microsoft.EntityFrameworkCore.Migrations;
-
-#nullable disable
-
-namespace CvSearch.Models.Migrations
-{
- ///
- public partial class AddJobSearchTables : Migration
- {
- ///
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.EnsureSchema(
- name: "cvSearch");
-
- migrationBuilder.CreateTable(
- name: "JobSearchResults",
- schema: "cvSearch",
- columns: table => new
- {
- Id = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false),
- SessionId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false),
- ProviderName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false),
- JobUrl = table.Column(type: "nvarchar(2048)", maxLength: 2048, nullable: false),
- JobTitle = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: false),
- JobText = table.Column(type: "nvarchar(max)", nullable: false),
- Score = table.Column(type: "int", nullable: false),
- ResultJson = table.Column(type: "nvarchar(max)", nullable: false),
- CreatedAt = table.Column(type: "datetime2", nullable: false, defaultValueSql: "SYSUTCDATETIME()")
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_JobSearchResults", x => x.Id);
- });
-
- migrationBuilder.CreateTable(
- name: "JobSearchSessions",
- schema: "cvSearch",
- columns: table => new
- {
- Id = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false),
- TokenId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false),
- CvDocumentId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false),
- Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false),
- Status = table.Column(type: "nvarchar(32)", maxLength: 32, nullable: false),
- Keywords = table.Column(type: "nvarchar(1000)", maxLength: 1000, nullable: false),
- ProviderConfigJson = table.Column(type: "nvarchar(max)", nullable: true),
- CreatedAt = table.Column(type: "datetime2", nullable: false, defaultValueSql: "SYSUTCDATETIME()")
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_JobSearchSessions", x => x.Id);
- });
-
- migrationBuilder.CreateTable(
- name: "JobSearchTokens",
- schema: "cvSearch",
- columns: table => new
- {
- Id = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false),
- CvDocumentId = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: false),
- Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false),
- ExpiresAt = table.Column(type: "datetime2", nullable: false),
- Used = table.Column(type: "bit", nullable: false, defaultValue: false),
- CreatedAt = table.Column(type: "datetime2", nullable: false, defaultValueSql: "SYSUTCDATETIME()")
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_JobSearchTokens", x => x.Id);
- });
-
- migrationBuilder.CreateIndex(
- name: "IX_JobSearchResults_SessionId",
- schema: "cvSearch",
- table: "JobSearchResults",
- column: "SessionId");
-
- migrationBuilder.CreateIndex(
- name: "IX_JobSearchSessions_Status",
- schema: "cvSearch",
- table: "JobSearchSessions",
- column: "Status");
- }
-
- ///
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.DropTable(
- name: "JobSearchResults",
- schema: "cvSearch");
-
- migrationBuilder.DropTable(
- name: "JobSearchSessions",
- schema: "cvSearch");
-
- migrationBuilder.DropTable(
- name: "JobSearchTokens",
- schema: "cvSearch");
- }
- }
-}
diff --git a/Apis/cv-search-models/Migrations/20260524145702_AddLanguageToJobSearchEntities.Designer.cs b/Apis/cv-search-models/Migrations/20260524145702_AddLanguageToJobSearchEntities.Designer.cs
deleted file mode 100644
index 68602de..0000000
--- a/Apis/cv-search-models/Migrations/20260524145702_AddLanguageToJobSearchEntities.Designer.cs
+++ /dev/null
@@ -1,174 +0,0 @@
-//
-using System;
-using CvSearch.Models.Data;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-
-#nullable disable
-
-namespace CvSearch.Models.Migrations
-{
- [DbContext(typeof(CvSearchDbContext))]
- [Migration("20260524145702_AddLanguageToJobSearchEntities")]
- partial class AddLanguageToJobSearchEntities
- {
- ///
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder
- .HasDefaultSchema("cvSearch")
- .HasAnnotation("ProductVersion", "10.0.7")
- .HasAnnotation("Relational:MaxIdentifierLength", 128);
-
- SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
-
- modelBuilder.Entity("CvSearch.Models.Data.Entities.JobSearchResultEntity", b =>
- {
- b.Property("Id")
- .HasMaxLength(64)
- .HasColumnType("nvarchar(64)");
-
- b.Property("CreatedAt")
- .ValueGeneratedOnAdd()
- .HasColumnType("datetime2")
- .HasDefaultValueSql("SYSUTCDATETIME()");
-
- b.Property("JobText")
- .IsRequired()
- .HasColumnType("nvarchar(max)");
-
- b.Property("JobTitle")
- .IsRequired()
- .HasMaxLength(512)
- .HasColumnType("nvarchar(512)");
-
- b.Property("JobUrl")
- .IsRequired()
- .HasMaxLength(2048)
- .HasColumnType("nvarchar(2048)");
-
- b.Property("ProviderName")
- .IsRequired()
- .HasMaxLength(128)
- .HasColumnType("nvarchar(128)");
-
- b.Property("ResultJson")
- .IsRequired()
- .HasColumnType("nvarchar(max)");
-
- b.Property("Score")
- .HasColumnType("int");
-
- b.Property("SessionId")
- .IsRequired()
- .HasMaxLength(64)
- .HasColumnType("nvarchar(64)");
-
- b.HasKey("Id");
-
- b.HasIndex("SessionId");
-
- b.ToTable("JobSearchResults", "cvSearch");
- });
-
- modelBuilder.Entity("CvSearch.Models.Data.Entities.JobSearchSessionEntity", b =>
- {
- b.Property("Id")
- .HasMaxLength(64)
- .HasColumnType("nvarchar(64)");
-
- b.Property("CreatedAt")
- .ValueGeneratedOnAdd()
- .HasColumnType("datetime2")
- .HasDefaultValueSql("SYSUTCDATETIME()");
-
- b.Property("CvDocumentId")
- .IsRequired()
- .HasMaxLength(64)
- .HasColumnType("nvarchar(64)");
-
- b.Property("Email")
- .IsRequired()
- .HasMaxLength(256)
- .HasColumnType("nvarchar(256)");
-
- b.Property("Keywords")
- .IsRequired()
- .HasMaxLength(1000)
- .HasColumnType("nvarchar(1000)");
-
- b.Property("Language")
- .IsRequired()
- .ValueGeneratedOnAdd()
- .HasMaxLength(8)
- .HasColumnType("nvarchar(8)")
- .HasDefaultValue("en");
-
- b.Property("ProviderConfigJson")
- .HasColumnType("nvarchar(max)");
-
- b.Property("Status")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("nvarchar(32)");
-
- b.Property("TokenId")
- .IsRequired()
- .HasMaxLength(64)
- .HasColumnType("nvarchar(64)");
-
- b.HasKey("Id");
-
- b.HasIndex("Status");
-
- b.ToTable("JobSearchSessions", "cvSearch");
- });
-
- modelBuilder.Entity("CvSearch.Models.Data.Entities.JobSearchTokenEntity", b =>
- {
- b.Property("Id")
- .HasMaxLength(64)
- .HasColumnType("nvarchar(64)");
-
- b.Property("CreatedAt")
- .ValueGeneratedOnAdd()
- .HasColumnType("datetime2")
- .HasDefaultValueSql("SYSUTCDATETIME()");
-
- b.Property("CvDocumentId")
- .IsRequired()
- .HasMaxLength(64)
- .HasColumnType("nvarchar(64)");
-
- b.Property("Email")
- .IsRequired()
- .HasMaxLength(256)
- .HasColumnType("nvarchar(256)");
-
- b.Property("ExpiresAt")
- .HasColumnType("datetime2");
-
- b.Property("Language")
- .IsRequired()
- .ValueGeneratedOnAdd()
- .HasMaxLength(8)
- .HasColumnType("nvarchar(8)")
- .HasDefaultValue("en");
-
- b.Property("Used")
- .ValueGeneratedOnAdd()
- .HasColumnType("bit")
- .HasDefaultValue(false);
-
- b.HasKey("Id");
-
- b.ToTable("JobSearchTokens", "cvSearch");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/Apis/cv-search-models/Migrations/20260524145702_AddLanguageToJobSearchEntities.cs b/Apis/cv-search-models/Migrations/20260524145702_AddLanguageToJobSearchEntities.cs
deleted file mode 100644
index ac5ea0b..0000000
--- a/Apis/cv-search-models/Migrations/20260524145702_AddLanguageToJobSearchEntities.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-using Microsoft.EntityFrameworkCore.Migrations;
-
-#nullable disable
-
-namespace CvSearch.Models.Migrations
-{
- ///
- public partial class AddLanguageToJobSearchEntities : Migration
- {
- ///
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.AddColumn(
- name: "Language",
- schema: "cvSearch",
- table: "JobSearchTokens",
- type: "nvarchar(8)",
- maxLength: 8,
- nullable: false,
- defaultValue: "en");
-
- migrationBuilder.AddColumn(
- name: "Language",
- schema: "cvSearch",
- table: "JobSearchSessions",
- type: "nvarchar(8)",
- maxLength: 8,
- nullable: false,
- defaultValue: "en");
- }
-
- ///
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.DropColumn(
- name: "Language",
- schema: "cvSearch",
- table: "JobSearchTokens");
-
- migrationBuilder.DropColumn(
- name: "Language",
- schema: "cvSearch",
- table: "JobSearchSessions");
- }
- }
-}
diff --git a/Apis/cv-search-models/Migrations/CvSearchDbContextModelSnapshot.cs b/Apis/cv-search-models/Migrations/CvSearchDbContextModelSnapshot.cs
deleted file mode 100644
index 5fd3d9e..0000000
--- a/Apis/cv-search-models/Migrations/CvSearchDbContextModelSnapshot.cs
+++ /dev/null
@@ -1,171 +0,0 @@
-//
-using System;
-using CvSearch.Models.Data;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-
-#nullable disable
-
-namespace CvSearch.Models.Migrations
-{
- [DbContext(typeof(CvSearchDbContext))]
- partial class CvSearchDbContextModelSnapshot : ModelSnapshot
- {
- protected override void BuildModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder
- .HasDefaultSchema("cvSearch")
- .HasAnnotation("ProductVersion", "10.0.7")
- .HasAnnotation("Relational:MaxIdentifierLength", 128);
-
- SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
-
- modelBuilder.Entity("CvSearch.Models.Data.Entities.JobSearchResultEntity", b =>
- {
- b.Property("Id")
- .HasMaxLength(64)
- .HasColumnType("nvarchar(64)");
-
- b.Property("CreatedAt")
- .ValueGeneratedOnAdd()
- .HasColumnType("datetime2")
- .HasDefaultValueSql("SYSUTCDATETIME()");
-
- b.Property("JobText")
- .IsRequired()
- .HasColumnType("nvarchar(max)");
-
- b.Property("JobTitle")
- .IsRequired()
- .HasMaxLength(512)
- .HasColumnType("nvarchar(512)");
-
- b.Property("JobUrl")
- .IsRequired()
- .HasMaxLength(2048)
- .HasColumnType("nvarchar(2048)");
-
- b.Property("ProviderName")
- .IsRequired()
- .HasMaxLength(128)
- .HasColumnType("nvarchar(128)");
-
- b.Property("ResultJson")
- .IsRequired()
- .HasColumnType("nvarchar(max)");
-
- b.Property("Score")
- .HasColumnType("int");
-
- b.Property("SessionId")
- .IsRequired()
- .HasMaxLength(64)
- .HasColumnType("nvarchar(64)");
-
- b.HasKey("Id");
-
- b.HasIndex("SessionId");
-
- b.ToTable("JobSearchResults", "cvSearch");
- });
-
- modelBuilder.Entity("CvSearch.Models.Data.Entities.JobSearchSessionEntity", b =>
- {
- b.Property("Id")
- .HasMaxLength(64)
- .HasColumnType("nvarchar(64)");
-
- b.Property("CreatedAt")
- .ValueGeneratedOnAdd()
- .HasColumnType("datetime2")
- .HasDefaultValueSql("SYSUTCDATETIME()");
-
- b.Property("CvDocumentId")
- .IsRequired()
- .HasMaxLength(64)
- .HasColumnType("nvarchar(64)");
-
- b.Property("Email")
- .IsRequired()
- .HasMaxLength(256)
- .HasColumnType("nvarchar(256)");
-
- b.Property("Keywords")
- .IsRequired()
- .HasMaxLength(1000)
- .HasColumnType("nvarchar(1000)");
-
- b.Property("Language")
- .IsRequired()
- .ValueGeneratedOnAdd()
- .HasMaxLength(8)
- .HasColumnType("nvarchar(8)")
- .HasDefaultValue("en");
-
- b.Property("ProviderConfigJson")
- .HasColumnType("nvarchar(max)");
-
- b.Property("Status")
- .IsRequired()
- .HasMaxLength(32)
- .HasColumnType("nvarchar(32)");
-
- b.Property("TokenId")
- .IsRequired()
- .HasMaxLength(64)
- .HasColumnType("nvarchar(64)");
-
- b.HasKey("Id");
-
- b.HasIndex("Status");
-
- b.ToTable("JobSearchSessions", "cvSearch");
- });
-
- modelBuilder.Entity("CvSearch.Models.Data.Entities.JobSearchTokenEntity", b =>
- {
- b.Property("Id")
- .HasMaxLength(64)
- .HasColumnType("nvarchar(64)");
-
- b.Property("CreatedAt")
- .ValueGeneratedOnAdd()
- .HasColumnType("datetime2")
- .HasDefaultValueSql("SYSUTCDATETIME()");
-
- b.Property("CvDocumentId")
- .IsRequired()
- .HasMaxLength(64)
- .HasColumnType("nvarchar(64)");
-
- b.Property("Email")
- .IsRequired()
- .HasMaxLength(256)
- .HasColumnType("nvarchar(256)");
-
- b.Property("ExpiresAt")
- .HasColumnType("datetime2");
-
- b.Property("Language")
- .IsRequired()
- .ValueGeneratedOnAdd()
- .HasMaxLength(8)
- .HasColumnType("nvarchar(8)")
- .HasDefaultValue("en");
-
- b.Property("Used")
- .ValueGeneratedOnAdd()
- .HasColumnType("bit")
- .HasDefaultValue(false);
-
- b.HasKey("Id");
-
- b.ToTable("JobSearchTokens", "cvSearch");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/Apis/cv-search-models/Settings/JobSearchSettings.cs b/Apis/cv-search-models/Settings/JobSearchSettings.cs
deleted file mode 100644
index 2634509..0000000
--- a/Apis/cv-search-models/Settings/JobSearchSettings.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-namespace CvSearch.Models.Settings;
-
-public sealed class JobSearchSettings
-{
- public bool Enabled { get; set; } = true;
- public string JobSearchLinkBaseUrl { get; set; } = string.Empty;
- public int TokenExpiryDays { get; set; } = 7;
- public int MinMatchScore { get; set; } = 15;
- public int MaxJobsToMatch { get; set; } = 15;
- public List Providers { get; set; } = [];
-}
-
-public sealed class JobProviderConfig
-{
- public string Name { get; set; } = string.Empty;
- public bool Enabled { get; set; } = true;
- public string SearchUrlTemplate { get; set; } = string.Empty;
- public string JobLinkContains { get; set; } = string.Empty;
- public List InitialKeywords { get; set; } = [];
- public int MaxResults { get; set; } = 20;
-}
diff --git a/Apis/cv-search-models/cv-search-models.csproj b/Apis/cv-search-models/cv-search-models.csproj
deleted file mode 100644
index 310b3cf..0000000
--- a/Apis/cv-search-models/cv-search-models.csproj
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
- net10.0
- CvSearch.Models
- enable
- enable
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
diff --git a/Apis/myai-data/myai-models.csproj b/Apis/myai-data/myai-models.csproj
deleted file mode 100644
index cf8d4c5..0000000
--- a/Apis/myai-data/myai-models.csproj
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
- net10.0
- MyAi.Models
- enable
- enable
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
diff --git a/Apis/myai-models/Migrations/20260524145351_AddTemplates.Designer.cs b/Apis/myai-models/Migrations/20260524145351_AddTemplates.Designer.cs
deleted file mode 100644
index 1e7b3c9..0000000
--- a/Apis/myai-models/Migrations/20260524145351_AddTemplates.Designer.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-using System;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-using MyAi.Models.Data;
-
-#nullable disable
-
-namespace MyAi.Models.Migrations
-{
- [DbContext(typeof(MyAiDbContext))]
- [Migration("20260524145351_AddTemplates")]
- partial class AddTemplates
- {
- ///
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder
- .HasDefaultSchema("myAi")
- .HasAnnotation("ProductVersion", "10.0.7")
- .HasAnnotation("Relational:MaxIdentifierLength", 128);
-
- SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
-
- modelBuilder.Entity("MyAi.Models.Data.Entities.TemplateEntity", b =>
- {
- b.Property("Key")
- .HasMaxLength(128)
- .HasColumnType("nvarchar(128)");
-
- b.Property("Language")
- .HasMaxLength(8)
- .HasColumnType("nvarchar(8)");
-
- b.Property("Description")
- .IsRequired()
- .ValueGeneratedOnAdd()
- .HasMaxLength(500)
- .HasColumnType("nvarchar(500)")
- .HasDefaultValue("");
-
- b.Property("UpdatedAt")
- .ValueGeneratedOnAdd()
- .HasColumnType("datetime2")
- .HasDefaultValueSql("SYSUTCDATETIME()");
-
- b.Property("Value")
- .IsRequired()
- .HasColumnType("nvarchar(max)");
-
- b.HasKey("Key", "Language");
-
- b.ToTable("Templates", "myAi");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/Apis/myai-models/Migrations/20260524145351_AddTemplates.cs b/Apis/myai-models/Migrations/20260524145351_AddTemplates.cs
deleted file mode 100644
index 299afc6..0000000
--- a/Apis/myai-models/Migrations/20260524145351_AddTemplates.cs
+++ /dev/null
@@ -1,113 +0,0 @@
-using System;
-using Microsoft.EntityFrameworkCore.Migrations;
-
-#nullable disable
-
-namespace MyAi.Models.Migrations
-{
- ///
- public partial class AddTemplates : Migration
- {
- ///
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.EnsureSchema(
- name: "myAi");
-
- migrationBuilder.CreateTable(
- name: "Templates",
- schema: "myAi",
- columns: table => new
- {
- Key = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false),
- Language = table.Column(type: "nvarchar(8)", maxLength: 8, nullable: false),
- Value = table.Column(type: "nvarchar(max)", nullable: false),
- Description = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: false, defaultValue: ""),
- UpdatedAt = table.Column(type: "datetime2", nullable: false, defaultValueSql: "SYSUTCDATETIME()")
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_Templates", x => new { x.Key, x.Language });
- });
-
- Seed(migrationBuilder);
- }
-
- private static void Seed(MigrationBuilder m)
- {
- void Row(string key, string lang, string value, string description = "")
- => m.InsertData("Templates", ["Key", "Language", "Value", "Description"], [key, lang, value, description], "myAi");
-
- // Match result email — subject
- Row("email.match.subject", "en", "MyAi.ro CV Match: {{score}}% - {{jobLabel}}", "Subject for the CV match result email");
- Row("email.match.subject", "ro", "MyAi.ro Potrivire CV: {{score}}% - {{jobLabel}}", "Subiect email rezultat potrivire CV");
-
- // Match result email — body
- Row("email.match.body", "en",
- "CV Matcher result\n\nCV Document ID: {{cvDocumentId}}\nJob: {{jobLabel}}\nJob URL: {{jobUrl}}\nScore: {{score}}%\n\nSummary:\n{{summary}}\n\nStrengths:\n{{strengths}}\n\nGaps:\n{{gaps}}\n\nRecommendations:\n{{recommendations}}",
- "Body for the CV match result email");
- Row("email.match.body", "ro",
- "Rezultat potrivire CV\n\nID document CV: {{cvDocumentId}}\nJob: {{jobLabel}}\nURL job: {{jobUrl}}\nScor: {{score}}%\n\nRezumat:\n{{summary}}\n\nPuncte forte:\n{{strengths}}\n\nLipsuri:\n{{gaps}}\n\nRecomandări:\n{{recommendations}}",
- "Corpul emailului pentru rezultatul potrivirii CV");
-
- // Match result email — job search CTA footer
- Row("email.match.job-search-footer", "en",
- "\n\n---\nWant to find more jobs matching your CV?\nClick: {{jobSearchLink}}\n(link valid for {{expiryDays}} days)",
- "Job search CTA appended to match result email");
- Row("email.match.job-search-footer", "ro",
- "\n\n---\nVrei sa gasesti mai multe joburi potrivite CV-ului tau?\nClick: {{jobSearchLink}}\n(link valabil {{expiryDays}} zile)",
- "CTA cautare joburi adaugat la emailul de potrivire CV");
-
- // Job search results email — subject
- Row("email.search-results.subject", "en", "MyAi.ro: {{count}} jobs matching your CV", "Subject for job search results email");
- Row("email.search-results.subject", "ro", "MyAi.ro: {{count}} joburi potrivite CV-ului tau", "Subiect email rezultate cautare joburi");
-
- // Job search results email — body preamble (items appended in code)
- Row("email.search-results.body", "en", "MyAi.ro found {{count}} jobs matching your CV:\n\n{{items}}", "Body preamble for job search results email");
- Row("email.search-results.body", "ro", "MyAi.ro a gasit {{count}} joburi potrivite CV-ului tau:\n\n{{items}}", "Corpul emailului de rezultate cautare joburi");
-
- // Job search results email — no results found
- Row("email.search-results.empty", "en", "MyAi.ro found no jobs matching your CV. Try again later or update your CV.", "No results message for job search results email");
- Row("email.search-results.empty", "ro", "MyAi.ro nu a gasit joburi care sa corespunda CV-ului tau. Incercati mai tarziu sau ajustati CV-ul.", "Mesaj fara rezultate pentru emailul de cautare joburi");
-
- // HTML job-search start page messages
- Row("html.job-search.started.title", "en", "Job search started", "Title for job search started page");
- Row("html.job-search.started.message", "en", "Your job search has started. Results will be sent to your email shortly.", "Message for job search started page");
- Row("html.job-search.started.title", "ro", "Căutare joburi pornită", "Titlu pagina cautare joburi pornita");
- Row("html.job-search.started.message", "ro", "Căutarea joburilor a început. Rezultatele vor fi trimise pe email în scurt timp.", "Mesaj pagina cautare joburi pornita");
-
- Row("html.job-search.already-used.title", "en", "Link already used", "Title for already-used page");
- Row("html.job-search.already-used.message", "en", "This job search link has already been used.", "Message for already-used page");
- Row("html.job-search.already-used.title", "ro", "Link deja folosit", "Titlu pagina link deja folosit");
- Row("html.job-search.already-used.message", "ro", "Acest link de cautare joburi a fost deja folosit.", "Mesaj pagina link deja folosit");
-
- Row("html.job-search.expired.title", "en", "Link expired", "Title for expired link page");
- Row("html.job-search.expired.message", "en", "This job search link has expired. Please request a new CV match to get a fresh link.", "Message for expired link page");
- Row("html.job-search.expired.title", "ro", "Link expirat", "Titlu pagina link expirat");
- Row("html.job-search.expired.message", "ro", "Acest link de cautare joburi a expirat. Solicita o noua potrivire CV pentru a primi un link nou.", "Mesaj pagina link expirat");
-
- Row("html.job-search.invalid.title", "en", "Invalid link", "Title for invalid link page");
- Row("html.job-search.invalid.message", "en", "This job search link is not valid.", "Message for invalid link page");
- Row("html.job-search.invalid.title", "ro", "Link invalid", "Titlu pagina link invalid");
- Row("html.job-search.invalid.message", "ro", "Acest link de cautare joburi nu este valid.", "Mesaj pagina link invalid");
-
- Row("html.job-search.error.title", "en", "Error", "Title for error page");
- Row("html.job-search.error.message", "en", "An error occurred. Please try again later.", "Message for error page");
- Row("html.job-search.error.title", "ro", "Eroare", "Titlu pagina eroare");
- Row("html.job-search.error.message", "ro", "A apărut o eroare. Te rugăm să încerci din nou mai târziu.", "Mesaj pagina eroare");
-
- // AI system prompt for CV matching (language is a {{languageName}} variable inside it)
- Row("ai.cv-match.system-prompt", "*",
- "You are a strict CV-to-job matching engine. Return JSON only. Score realistically from 0 to 100.\nPenalize missing required skills. Do not invent experience. Use concise business language.\nRespond entirely in {{languageName}} — all text fields in the JSON must be in {{languageName}}.\nJSON shape: {\"score\":number,\"summary\":\"...\",\"strengths\":[\"...\"],\"gaps\":[\"...\"],\"recommendations\":[\"...\"],\"evidence\":[\"...\"]}",
- "System prompt template for the CV-to-job LLM matching call. {{languageName}} is substituted at runtime.");
- }
-
- ///
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.DropTable(
- name: "Templates",
- schema: "myAi");
- }
- }
-}
diff --git a/Apis/myai-models/Migrations/MyAiDbContextModelSnapshot.cs b/Apis/myai-models/Migrations/MyAiDbContextModelSnapshot.cs
deleted file mode 100644
index d9a7549..0000000
--- a/Apis/myai-models/Migrations/MyAiDbContextModelSnapshot.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-//
-using System;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-using MyAi.Models.Data;
-
-#nullable disable
-
-namespace MyAi.Models.Migrations
-{
- [DbContext(typeof(MyAiDbContext))]
- partial class MyAiDbContextModelSnapshot : ModelSnapshot
- {
- protected override void BuildModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder
- .HasDefaultSchema("myAi")
- .HasAnnotation("ProductVersion", "10.0.7")
- .HasAnnotation("Relational:MaxIdentifierLength", 128);
-
- SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
-
- modelBuilder.Entity("MyAi.Models.Data.Entities.TemplateEntity", b =>
- {
- b.Property("Key")
- .HasMaxLength(128)
- .HasColumnType("nvarchar(128)");
-
- b.Property("Language")
- .HasMaxLength(8)
- .HasColumnType("nvarchar(8)");
-
- b.Property("Description")
- .IsRequired()
- .ValueGeneratedOnAdd()
- .HasMaxLength(500)
- .HasColumnType("nvarchar(500)")
- .HasDefaultValue("");
-
- b.Property("UpdatedAt")
- .ValueGeneratedOnAdd()
- .HasColumnType("datetime2")
- .HasDefaultValueSql("SYSUTCDATETIME()");
-
- b.Property("Value")
- .IsRequired()
- .HasColumnType("nvarchar(max)");
-
- b.HasKey("Key", "Language");
-
- b.ToTable("Templates", "myAi");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/Apis/myai-models/Services/DbTemplateService.cs b/Apis/myai-models/Services/DbTemplateService.cs
deleted file mode 100644
index a19a48f..0000000
--- a/Apis/myai-models/Services/DbTemplateService.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
-using MyAi.Models.Data;
-using System.Collections.Concurrent;
-
-namespace MyAi.Models.Services;
-
-public sealed class DbTemplateService : ITemplateService
-{
- private readonly IServiceScopeFactory _scopeFactory;
- private readonly ILogger _logger;
- private ConcurrentDictionary _cache = new(StringComparer.OrdinalIgnoreCase);
- private DateTime _loadedAt = DateTime.MinValue;
- private static readonly TimeSpan CacheTtl = TimeSpan.FromMinutes(10);
-
- public DbTemplateService(IServiceScopeFactory scopeFactory, ILogger logger)
- {
- _scopeFactory = scopeFactory;
- _logger = logger;
- }
-
- public string Get(string key, string language = "en")
- {
- EnsureCacheLoaded();
-
- if (_cache.TryGetValue(CacheKey(key, language), out var value))
- return value;
-
- if (!string.Equals(language, "en", StringComparison.OrdinalIgnoreCase)
- && _cache.TryGetValue(CacheKey(key, "en"), out var fallback))
- return fallback;
-
- _logger.LogWarning("Template not found: key={Key}, language={Language}", key, language);
- return key;
- }
-
- public string Render(string key, string language, params (string Key, string Value)[] placeholders)
- {
- var template = Get(key, language);
- foreach (var (k, v) in placeholders)
- template = template.Replace($"{{{{{k}}}}}", v, StringComparison.OrdinalIgnoreCase);
- return template;
- }
-
- private void EnsureCacheLoaded()
- {
- if (DateTime.UtcNow - _loadedAt < CacheTtl) return;
-
- try
- {
- using var scope = _scopeFactory.CreateScope();
- var db = scope.ServiceProvider.GetRequiredService();
- var rows = db.Templates.AsNoTracking().ToList();
- var fresh = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase);
- foreach (var row in rows)
- fresh[CacheKey(row.Key, row.Language)] = row.Value;
-
- _cache = fresh;
- _loadedAt = DateTime.UtcNow;
- _logger.LogDebug("Template cache refreshed. {Count} templates loaded.", rows.Count);
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Failed to refresh template cache. Serving stale cache.");
- }
- }
-
- private static string CacheKey(string key, string language) => $"{key}::{language}";
-}
diff --git a/Apis/myai-models/Services/ITemplateService.cs b/Apis/myai-models/Services/ITemplateService.cs
deleted file mode 100644
index 50eaad8..0000000
--- a/Apis/myai-models/Services/ITemplateService.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace MyAi.Models.Services;
-
-public interface ITemplateService
-{
- string Get(string key, string language = "en");
- string Render(string key, string language, params (string Key, string Value)[] placeholders);
-}
diff --git a/Apis/myai-models/myai-models.csproj b/Apis/myai-models/myai-models.csproj
deleted file mode 100644
index cf8d4c5..0000000
--- a/Apis/myai-models/myai-models.csproj
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
- net10.0
- MyAi.Models
- enable
- enable
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-