using ControlCenter.Api.Entities; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; namespace ControlCenter.Api.Configurations; /// /// EF Core entity type configuration for the agents table. /// Enforces snake_case naming, required fields, and index design. /// public class AgentConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { // Table name — snake_case builder.ToTable("agents"); // Primary key builder.HasKey(a => a.Id); builder.Property(a => a.Id) .HasColumnName("id") .ValueGeneratedOnAdd(); // Status — stored as PostgreSQL enum via Npgsql builder.Property(a => a.Status) .HasColumnName("status") .HasColumnType("agent_status") .IsRequired(); // Task — nullable text builder.Property(a => a.Task) .HasColumnName("task") .HasColumnType("text"); // Progress — nullable integer (0–100) builder.Property(a => a.Progress) .HasColumnName("progress"); // Session key — required, not null builder.Property(a => a.SessionKey) .HasColumnName("session_key") .HasColumnType("text") .IsRequired(); // Channel — required, not null builder.Property(a => a.Channel) .HasColumnName("channel") .HasColumnType("text") .IsRequired(); // Last activity — required, defaults to now() builder.Property(a => a.LastActivity) .HasColumnName("last_activity") .HasColumnType("timestamptz") .IsRequired(); // Created at — auto-set on insert builder.Property(a => a.CreatedAt) .HasColumnName("created_at") .HasColumnType("timestamptz") .IsRequired() .HasDefaultValueSql("now()"); // Updated at — auto-set on insert and update builder.Property(a => a.UpdatedAt) .HasColumnName("updated_at") .HasColumnType("timestamptz") .IsRequired() .HasDefaultValueSql("now()"); // Indexes // Sessions are looked up by session_key frequently builder.HasIndex(a => a.SessionKey) .HasDatabaseName("ix_agents_session_key") .IsUnique(); // Agents are filtered by channel for channel-specific queries builder.HasIndex(a => a.Channel) .HasDatabaseName("ix_agents_channel"); // Agents are filtered by status for fleet health monitoring builder.HasIndex(a => a.Status) .HasDatabaseName("ix_agents_status"); // Check constraint: progress must be 0–100 if present builder.ToTable(t => t.HasCheckConstraint("ck_agents_progress_range", "progress IS NULL OR (progress >= 0 AND progress <= 100)")); } }