wip: doctor/cli/docs/api to vector db consolidation; api hardening for descriptions, tenant, and scopes; migrations and conversions of all DALs to EF v10

This commit is contained in:
master
2026-02-23 15:30:50 +02:00
parent bd8fee6ed8
commit e746577380
1424 changed files with 81225 additions and 25251 deletions

View File

@@ -0,0 +1,37 @@
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
#pragma warning disable 219, 612, 618
#nullable disable
namespace StellaOps.Remediation.Persistence.EfCore.CompiledModels;
/// <summary>
/// Compiled model stub for RemediationDbContext.
/// This is a placeholder that delegates to runtime model building.
/// Replace with output from <c>dotnet ef dbcontext optimize</c> when a provisioned DB is available.
/// </summary>
[DbContext(typeof(Context.RemediationDbContext))]
public partial class RemediationDbContextModel : RuntimeModel
{
private static RemediationDbContextModel _instance;
public static IModel Instance
{
get
{
if (_instance == null)
{
_instance = new RemediationDbContextModel();
_instance.Initialize();
_instance.Customize();
}
return _instance;
}
}
partial void Initialize();
partial void Customize();
}

View File

@@ -0,0 +1,23 @@
using Microsoft.EntityFrameworkCore;
using StellaOps.Remediation.Persistence.EfCore.Models;
namespace StellaOps.Remediation.Persistence.EfCore.Context;
public partial class RemediationDbContext
{
/// <summary>
/// Relationship overlays and navigation property configuration.
/// </summary>
partial void OnModelCreatingPartial(ModelBuilder modelBuilder)
{
// pr_submissions.fix_template_id -> fix_templates.id foreign key
modelBuilder.Entity<PrSubmissionEntity>(entity =>
{
entity.HasOne<FixTemplateEntity>()
.WithMany()
.HasForeignKey(e => e.FixTemplateId)
.HasConstraintName("pr_submissions_fix_template_id_fkey")
.OnDelete(DeleteBehavior.SetNull);
});
}
}

View File

@@ -0,0 +1,162 @@
using Microsoft.EntityFrameworkCore;
using StellaOps.Remediation.Persistence.EfCore.Models;
namespace StellaOps.Remediation.Persistence.EfCore.Context;
/// <summary>
/// EF Core DbContext for the Remediation module.
/// Maps to the remediation PostgreSQL schema: fix_templates, pr_submissions,
/// contributors, and marketplace_sources tables.
/// </summary>
public partial class RemediationDbContext : DbContext
{
private readonly string _schemaName;
public RemediationDbContext(DbContextOptions<RemediationDbContext> options, string? schemaName = null)
: base(options)
{
_schemaName = string.IsNullOrWhiteSpace(schemaName)
? "remediation"
: schemaName.Trim();
}
public virtual DbSet<FixTemplateEntity> FixTemplates { get; set; }
public virtual DbSet<PrSubmissionEntity> PrSubmissions { get; set; }
public virtual DbSet<ContributorEntity> Contributors { get; set; }
public virtual DbSet<MarketplaceSourceEntity> MarketplaceSources { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var schemaName = _schemaName;
// -- fix_templates -----------------------------------------------
modelBuilder.Entity<FixTemplateEntity>(entity =>
{
entity.HasKey(e => e.Id).HasName("fix_templates_pkey");
entity.ToTable("fix_templates", schemaName);
entity.HasIndex(e => e.CveId, "idx_fix_templates_cve");
entity.HasIndex(e => e.Purl, "idx_fix_templates_purl");
entity.Property(e => e.Id)
.HasDefaultValueSql("gen_random_uuid()")
.HasColumnName("id");
entity.Property(e => e.CveId).HasColumnName("cve_id");
entity.Property(e => e.Purl).HasColumnName("purl");
entity.Property(e => e.VersionRange).HasColumnName("version_range");
entity.Property(e => e.PatchContent).HasColumnName("patch_content");
entity.Property(e => e.Description).HasColumnName("description");
entity.Property(e => e.ContributorId).HasColumnName("contributor_id");
entity.Property(e => e.SourceId).HasColumnName("source_id");
entity.Property(e => e.Status)
.HasDefaultValueSql("'pending'")
.HasColumnName("status");
entity.Property(e => e.TrustScore)
.HasDefaultValue(0.0)
.HasColumnName("trust_score");
entity.Property(e => e.DsseDigest).HasColumnName("dsse_digest");
entity.Property(e => e.CreatedAt)
.HasDefaultValueSql("now()")
.HasColumnName("created_at");
entity.Property(e => e.VerifiedAt).HasColumnName("verified_at");
});
// -- pr_submissions ----------------------------------------------
modelBuilder.Entity<PrSubmissionEntity>(entity =>
{
entity.HasKey(e => e.Id).HasName("pr_submissions_pkey");
entity.ToTable("pr_submissions", schemaName);
entity.HasIndex(e => e.CveId, "idx_pr_submissions_cve");
entity.HasIndex(e => e.Status, "idx_pr_submissions_status");
entity.Property(e => e.Id)
.HasDefaultValueSql("gen_random_uuid()")
.HasColumnName("id");
entity.Property(e => e.FixTemplateId).HasColumnName("fix_template_id");
entity.Property(e => e.PrUrl).HasColumnName("pr_url");
entity.Property(e => e.RepositoryUrl).HasColumnName("repository_url");
entity.Property(e => e.SourceBranch).HasColumnName("source_branch");
entity.Property(e => e.TargetBranch).HasColumnName("target_branch");
entity.Property(e => e.CveId).HasColumnName("cve_id");
entity.Property(e => e.Status)
.HasDefaultValueSql("'opened'")
.HasColumnName("status");
entity.Property(e => e.PreScanDigest).HasColumnName("pre_scan_digest");
entity.Property(e => e.PostScanDigest).HasColumnName("post_scan_digest");
entity.Property(e => e.ReachabilityDeltaDigest).HasColumnName("reachability_delta_digest");
entity.Property(e => e.FixChainDsseDigest).HasColumnName("fix_chain_dsse_digest");
entity.Property(e => e.Verdict).HasColumnName("verdict");
entity.Property(e => e.ContributorId).HasColumnName("contributor_id");
entity.Property(e => e.CreatedAt)
.HasDefaultValueSql("now()")
.HasColumnName("created_at");
entity.Property(e => e.MergedAt).HasColumnName("merged_at");
entity.Property(e => e.VerifiedAt).HasColumnName("verified_at");
});
// -- contributors ------------------------------------------------
modelBuilder.Entity<ContributorEntity>(entity =>
{
entity.HasKey(e => e.Id).HasName("contributors_pkey");
entity.ToTable("contributors", schemaName);
entity.HasAlternateKey(e => e.Username).HasName("contributors_username_key");
entity.Property(e => e.Id)
.HasDefaultValueSql("gen_random_uuid()")
.HasColumnName("id");
entity.Property(e => e.Username).HasColumnName("username");
entity.Property(e => e.DisplayName).HasColumnName("display_name");
entity.Property(e => e.VerifiedFixes)
.HasDefaultValue(0)
.HasColumnName("verified_fixes");
entity.Property(e => e.TotalSubmissions)
.HasDefaultValue(0)
.HasColumnName("total_submissions");
entity.Property(e => e.RejectedSubmissions)
.HasDefaultValue(0)
.HasColumnName("rejected_submissions");
entity.Property(e => e.TrustScore)
.HasDefaultValue(0.0)
.HasColumnName("trust_score");
entity.Property(e => e.CreatedAt)
.HasDefaultValueSql("now()")
.HasColumnName("created_at");
entity.Property(e => e.LastActiveAt).HasColumnName("last_active_at");
});
// -- marketplace_sources -----------------------------------------
modelBuilder.Entity<MarketplaceSourceEntity>(entity =>
{
entity.HasKey(e => e.Id).HasName("marketplace_sources_pkey");
entity.ToTable("marketplace_sources", schemaName);
entity.HasAlternateKey(e => e.Key).HasName("marketplace_sources_key_key");
entity.Property(e => e.Id)
.HasDefaultValueSql("gen_random_uuid()")
.HasColumnName("id");
entity.Property(e => e.Key).HasColumnName("key");
entity.Property(e => e.Name).HasColumnName("name");
entity.Property(e => e.Url).HasColumnName("url");
entity.Property(e => e.SourceType)
.HasDefaultValueSql("'community'")
.HasColumnName("source_type");
entity.Property(e => e.Enabled)
.HasDefaultValue(true)
.HasColumnName("enabled");
entity.Property(e => e.TrustScore)
.HasDefaultValue(0.0)
.HasColumnName("trust_score");
entity.Property(e => e.CreatedAt)
.HasDefaultValueSql("now()")
.HasColumnName("created_at");
entity.Property(e => e.LastSyncAt).HasColumnName("last_sync_at");
});
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}

View File

@@ -0,0 +1,31 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
namespace StellaOps.Remediation.Persistence.EfCore.Context;
/// <summary>
/// Design-time factory for <see cref="RemediationDbContext"/>.
/// Used by <c>dotnet ef</c> CLI tooling for scaffold and optimize commands.
/// </summary>
public sealed class RemediationDesignTimeDbContextFactory : IDesignTimeDbContextFactory<RemediationDbContext>
{
private const string DefaultConnectionString =
"Host=localhost;Port=55433;Database=postgres;Username=postgres;Password=postgres;Search Path=remediation,public";
private const string ConnectionStringEnvironmentVariable = "STELLAOPS_REMEDIATION_EF_CONNECTION";
public RemediationDbContext CreateDbContext(string[] args)
{
var connectionString = ResolveConnectionString();
var options = new DbContextOptionsBuilder<RemediationDbContext>()
.UseNpgsql(connectionString)
.Options;
return new RemediationDbContext(options);
}
private static string ResolveConnectionString()
{
var fromEnvironment = Environment.GetEnvironmentVariable(ConnectionStringEnvironmentVariable);
return string.IsNullOrWhiteSpace(fromEnvironment) ? DefaultConnectionString : fromEnvironment;
}
}

View File

@@ -0,0 +1,25 @@
namespace StellaOps.Remediation.Persistence.EfCore.Models;
/// <summary>
/// EF Core entity for the remediation.contributors table.
/// </summary>
public partial class ContributorEntity
{
public Guid Id { get; set; }
public string Username { get; set; } = null!;
public string? DisplayName { get; set; }
public int VerifiedFixes { get; set; }
public int TotalSubmissions { get; set; }
public int RejectedSubmissions { get; set; }
public double TrustScore { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime? LastActiveAt { get; set; }
}

View File

@@ -0,0 +1,33 @@
namespace StellaOps.Remediation.Persistence.EfCore.Models;
/// <summary>
/// EF Core entity for the remediation.fix_templates table.
/// </summary>
public partial class FixTemplateEntity
{
public Guid Id { get; set; }
public string CveId { get; set; } = null!;
public string Purl { get; set; } = null!;
public string VersionRange { get; set; } = null!;
public string PatchContent { get; set; } = null!;
public string? Description { get; set; }
public Guid? ContributorId { get; set; }
public Guid? SourceId { get; set; }
public string Status { get; set; } = null!;
public double TrustScore { get; set; }
public string? DsseDigest { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime? VerifiedAt { get; set; }
}

View File

@@ -0,0 +1,25 @@
namespace StellaOps.Remediation.Persistence.EfCore.Models;
/// <summary>
/// EF Core entity for the remediation.marketplace_sources table.
/// </summary>
public partial class MarketplaceSourceEntity
{
public Guid Id { get; set; }
public string Key { get; set; } = null!;
public string Name { get; set; } = null!;
public string? Url { get; set; }
public string SourceType { get; set; } = null!;
public bool Enabled { get; set; }
public double TrustScore { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime? LastSyncAt { get; set; }
}

View File

@@ -0,0 +1,41 @@
namespace StellaOps.Remediation.Persistence.EfCore.Models;
/// <summary>
/// EF Core entity for the remediation.pr_submissions table.
/// </summary>
public partial class PrSubmissionEntity
{
public Guid Id { get; set; }
public Guid? FixTemplateId { get; set; }
public string PrUrl { get; set; } = null!;
public string RepositoryUrl { get; set; } = null!;
public string SourceBranch { get; set; } = null!;
public string TargetBranch { get; set; } = null!;
public string CveId { get; set; } = null!;
public string Status { get; set; } = null!;
public string? PreScanDigest { get; set; }
public string? PostScanDigest { get; set; }
public string? ReachabilityDeltaDigest { get; set; }
public string? FixChainDsseDigest { get; set; }
public string? Verdict { get; set; }
public Guid? ContributorId { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime? MergedAt { get; set; }
public DateTime? VerifiedAt { get; set; }
}