Add Rider launch profiles, fix DI and migrations for dev startup

- Rider launch profiles: "ScadaLink Central" and "ScadaLink Site"
- appsettings.Central.json: correct test_infra credentials (ScadaLink_Dev1#,
  scadalink_app user, GLAuth on 3893, Mailpit on 1025)
- Fix HealthMonitoring DI: split site vs central registration to avoid
  missing IHealthReportTransport on central
- Regenerate single clean EF migration (InitialSchema) covering all entities
- Suppress PendingModelChangesWarning in dev mode
- Fix isDevelopment check for ASPNETCORE_ENVIRONMENT propagation

Verified: Host starts, connects to SQL Server, applies migrations, boots
Akka.NET cluster, LDAP auth works (admin/password via GLAuth), health
endpoint returns Healthy.
This commit is contained in:
Joseph Doherty
2026-03-17 03:01:21 -04:00
parent 2b2cc0a151
commit 121983fd66
11 changed files with 1721 additions and 1187 deletions

View File

@@ -1,28 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ScadaLink.ConfigurationDatabase.Migrations
{
/// <inheritdoc />
public partial class SeedData : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.InsertData(
table: "LdapGroupMappings",
columns: new[] { "Id", "LdapGroupName", "Role" },
values: new object[] { 1, "SCADA-Admins", "Admin" });
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "LdapGroupMappings",
keyColumn: "Id",
keyValue: 1);
}
}
}

View File

@@ -12,8 +12,8 @@ using ScadaLink.ConfigurationDatabase;
namespace ScadaLink.ConfigurationDatabase.Migrations
{
[DbContext(typeof(ScadaLinkDbContext))]
[Migration("20260316231942_SeedData")]
partial class SeedData
[Migration("20260317065749_InitialSchema")]
partial class InitialSchema
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@@ -25,6 +25,25 @@ namespace ScadaLink.ConfigurationDatabase.Migrations
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("FriendlyName")
.HasColumnType("nvarchar(max)");
b.Property<string>("Xml")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("DataProtectionKeys");
});
modelBuilder.Entity("ScadaLink.Commons.Entities.Audit.AuditLogEntry", b =>
{
b.Property<int>("Id")
@@ -79,6 +98,44 @@ namespace ScadaLink.ConfigurationDatabase.Migrations
b.ToTable("AuditLogEntries");
});
modelBuilder.Entity("ScadaLink.Commons.Entities.Deployment.DeployedConfigSnapshot", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ConfigurationJson")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<DateTimeOffset>("DeployedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("DeploymentId")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<int>("InstanceId")
.HasColumnType("int");
b.Property<string>("RevisionHash")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.HasKey("Id");
b.HasIndex("DeploymentId");
b.HasIndex("InstanceId")
.IsUnique();
b.ToTable("DeployedConfigSnapshots");
});
modelBuilder.Entity("ScadaLink.Commons.Entities.Deployment.DeploymentRecord", b =>
{
b.Property<int>("Id")
@@ -103,6 +160,9 @@ namespace ScadaLink.ConfigurationDatabase.Migrations
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<string>("ErrorMessage")
.HasColumnType("nvarchar(max)");
b.Property<int>("InstanceId")
.HasColumnType("int");
@@ -112,6 +172,7 @@ namespace ScadaLink.ConfigurationDatabase.Migrations
b.Property<byte[]>("RowVersion")
.IsConcurrencyToken()
.IsRequired()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("rowversion");
@@ -954,6 +1015,15 @@ namespace ScadaLink.ConfigurationDatabase.Migrations
b.ToTable("TemplateScripts");
});
modelBuilder.Entity("ScadaLink.Commons.Entities.Deployment.DeployedConfigSnapshot", b =>
{
b.HasOne("ScadaLink.Commons.Entities.Instances.Instance", null)
.WithMany()
.HasForeignKey("InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("ScadaLink.Commons.Entities.Deployment.DeploymentRecord", b =>
{
b.HasOne("ScadaLink.Commons.Entities.Instances.Instance", null)

View File

@@ -6,7 +6,7 @@ using Microsoft.EntityFrameworkCore.Migrations;
namespace ScadaLink.ConfigurationDatabase.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
public partial class InitialSchema : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
@@ -94,6 +94,20 @@ namespace ScadaLink.ConfigurationDatabase.Migrations
table.PrimaryKey("PK_DataConnections", x => x.Id);
});
migrationBuilder.CreateTable(
name: "DataProtectionKeys",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
FriendlyName = table.Column<string>(type: "nvarchar(max)", nullable: true),
Xml = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_DataProtectionKeys", x => x.Id);
});
migrationBuilder.CreateTable(
name: "ExternalSystemDefinitions",
columns: table => new
@@ -493,6 +507,29 @@ namespace ScadaLink.ConfigurationDatabase.Migrations
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "DeployedConfigSnapshots",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
InstanceId = table.Column<int>(type: "int", nullable: false),
DeploymentId = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
RevisionHash = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
ConfigurationJson = table.Column<string>(type: "nvarchar(max)", nullable: false),
DeployedAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_DeployedConfigSnapshots", x => x.Id);
table.ForeignKey(
name: "FK_DeployedConfigSnapshots_Instances_InstanceId",
column: x => x.InstanceId,
principalTable: "Instances",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "DeploymentRecords",
columns: table => new
@@ -506,7 +543,8 @@ namespace ScadaLink.ConfigurationDatabase.Migrations
DeployedBy = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
DeployedAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: false),
CompletedAt = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
RowVersion = table.Column<byte[]>(type: "rowversion", rowVersion: true, nullable: true)
ErrorMessage = table.Column<string>(type: "nvarchar(max)", nullable: true),
RowVersion = table.Column<byte[]>(type: "rowversion", rowVersion: true, nullable: false)
},
constraints: table =>
{
@@ -567,6 +605,11 @@ namespace ScadaLink.ConfigurationDatabase.Migrations
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.InsertData(
table: "LdapGroupMappings",
columns: new[] { "Id", "LdapGroupName", "Role" },
values: new object[] { 1, "SCADA-Admins", "Admin" });
migrationBuilder.CreateIndex(
name: "IX_ApiKeys_KeyValue",
table: "ApiKeys",
@@ -634,6 +677,17 @@ namespace ScadaLink.ConfigurationDatabase.Migrations
column: "Name",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_DeployedConfigSnapshots_DeploymentId",
table: "DeployedConfigSnapshots",
column: "DeploymentId");
migrationBuilder.CreateIndex(
name: "IX_DeployedConfigSnapshots_InstanceId",
table: "DeployedConfigSnapshots",
column: "InstanceId",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_DeploymentRecords_DeployedAt",
table: "DeploymentRecords",
@@ -813,6 +867,12 @@ namespace ScadaLink.ConfigurationDatabase.Migrations
migrationBuilder.DropTable(
name: "DatabaseConnectionDefinitions");
migrationBuilder.DropTable(
name: "DataProtectionKeys");
migrationBuilder.DropTable(
name: "DeployedConfigSnapshots");
migrationBuilder.DropTable(
name: "DeploymentRecords");

View File

@@ -22,6 +22,25 @@ namespace ScadaLink.ConfigurationDatabase.Migrations
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("FriendlyName")
.HasColumnType("nvarchar(max)");
b.Property<string>("Xml")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("DataProtectionKeys");
});
modelBuilder.Entity("ScadaLink.Commons.Entities.Audit.AuditLogEntry", b =>
{
b.Property<int>("Id")
@@ -76,6 +95,44 @@ namespace ScadaLink.ConfigurationDatabase.Migrations
b.ToTable("AuditLogEntries");
});
modelBuilder.Entity("ScadaLink.Commons.Entities.Deployment.DeployedConfigSnapshot", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("ConfigurationJson")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<DateTimeOffset>("DeployedAt")
.HasColumnType("datetimeoffset");
b.Property<string>("DeploymentId")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<int>("InstanceId")
.HasColumnType("int");
b.Property<string>("RevisionHash")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.HasKey("Id");
b.HasIndex("DeploymentId");
b.HasIndex("InstanceId")
.IsUnique();
b.ToTable("DeployedConfigSnapshots");
});
modelBuilder.Entity("ScadaLink.Commons.Entities.Deployment.DeploymentRecord", b =>
{
b.Property<int>("Id")
@@ -100,6 +157,9 @@ namespace ScadaLink.ConfigurationDatabase.Migrations
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<string>("ErrorMessage")
.HasColumnType("nvarchar(max)");
b.Property<int>("InstanceId")
.HasColumnType("int");
@@ -109,6 +169,7 @@ namespace ScadaLink.ConfigurationDatabase.Migrations
b.Property<byte[]>("RowVersion")
.IsConcurrencyToken()
.IsRequired()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("rowversion");
@@ -951,6 +1012,15 @@ namespace ScadaLink.ConfigurationDatabase.Migrations
b.ToTable("TemplateScripts");
});
modelBuilder.Entity("ScadaLink.Commons.Entities.Deployment.DeployedConfigSnapshot", b =>
{
b.HasOne("ScadaLink.Commons.Entities.Instances.Instance", null)
.WithMany()
.HasForeignKey("InstanceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("ScadaLink.Commons.Entities.Deployment.DeploymentRecord", b =>
{
b.HasOne("ScadaLink.Commons.Entities.Instances.Instance", null)