From 54753bfd41afce421de8062d8bf2cb46fe638131 Mon Sep 17 00:00:00 2001
From: master <>
Date: Fri, 6 Mar 2026 00:40:59 +0200
Subject: [PATCH] qa iteration 2
---
AGENTS.md | 14 +++++++++++++-
docs/code-of-conduct/CODE_OF_CONDUCT.md | 1 +
.../StellaOps.Integrations.WebService/Program.cs | 15 +++++++++++++++
.../Extensions/NotifyPersistenceExtensions.cs | 7 +++++++
.../StellaOps.Platform.WebService/Program.cs | 8 ++++++++
5 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/AGENTS.md b/AGENTS.md
index 6d4c4fef5..9cab0c048 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -107,7 +107,19 @@ Whenever a new dependency, container image, tool, or vendored asset is added:
- If compatibility is unclear, mark the sprint task `BLOCKED` and record the
risk in `Decisions & Risks`.
-### 2.7 Web tool policy (security constraint)
+### 2.7 Database auto-migration requirement (non-negotiable)
+Every service that owns a PostgreSQL schema MUST auto-migrate on startup. Manual init scripts (`postgres-init/`) are only bootstrap fallbacks for first-run, NOT the migration authority.
+
+Rules:
+- Wire `AddStartupMigrations(schemaName, moduleName, migrationsAssembly)` from `StellaOps.Infrastructure.Postgres.Migrations` in the service's persistence registration or `Program.cs`.
+- SQL migration files MUST be embedded resources in the persistence library (`.csproj`: ``).
+- For EF Core services without the Infrastructure.Postgres dependency, use `EnsureCreatedAsync()` or a custom `IHostedService` that applies schema on startup.
+- The service MUST converge to the correct schema on any fresh database — volume resets, CI environments, and new installs must work without manual `psql` or external scripts.
+- Pattern references: `src/Signals/__Libraries/StellaOps.Signals.Persistence/Extensions/`, `src/Scanner/__Libraries/StellaOps.Scanner.Storage/Extensions/`.
+
+Rationale: Missing database tables are the #1 cause of 500 errors in QA. Relying on external init scripts creates a fragile dependency chain that breaks on volume resets and CI.
+
+### 2.8 Web tool policy (security constraint)
AI agents with web access (WebFetch, WebSearch, or similar) must follow these rules:
1. **Default: no external web fetching** – Prefer local docs (`docs/**`), codebase search, and existing fixtures. External fetches introduce prompt-injection risk, non-determinism, and violate the offline-first posture.
diff --git a/docs/code-of-conduct/CODE_OF_CONDUCT.md b/docs/code-of-conduct/CODE_OF_CONDUCT.md
index 64038481c..8abc40a1e 100644
--- a/docs/code-of-conduct/CODE_OF_CONDUCT.md
+++ b/docs/code-of-conduct/CODE_OF_CONDUCT.md
@@ -91,6 +91,7 @@ These checklists are mandatory. Pick the relevant checklist(s) and satisfy them.
- [ ] Indexing considered for new query patterns.
- [ ] Serialization round-trip tests updated/added.
- [ ] Roll-forward behavior documented; rollback constraints noted.
+- [ ] **Startup auto-migration wired** (CRITICAL): Every service that owns a PostgreSQL schema MUST run its migrations automatically on startup via `AddStartupMigrations` (from `StellaOps.Infrastructure.Postgres.Migrations`) or an equivalent `IHostedService`. Relying on external init scripts or manual `psql` execution is forbidden for service-owned schemas. This ensures fresh installs, volume resets, and CI environments always converge to the correct schema without manual intervention. Pattern: `services.AddStartupMigrations(schemaName, moduleName, migrationsAssembly)`. SQL migrations must be embedded resources in the persistence library.
### 4.5 Security-sensitive change
- [ ] Threat note added in sprint "Decisions & Risks" (what can go wrong + mitigation).
diff --git a/src/Integrations/StellaOps.Integrations.WebService/Program.cs b/src/Integrations/StellaOps.Integrations.WebService/Program.cs
index c60f494b9..f36b0a2e6 100644
--- a/src/Integrations/StellaOps.Integrations.WebService/Program.cs
+++ b/src/Integrations/StellaOps.Integrations.WebService/Program.cs
@@ -96,6 +96,21 @@ builder.TryAddStellaOpsLocalBinding("integrations");
var app = builder.Build();
app.LogStellaOpsLocalHostname("integrations");
+// Auto-migrate: ensure integrations schema and tables exist on startup
+using (var scope = app.Services.CreateScope())
+{
+ var db = scope.ServiceProvider.GetRequiredService();
+ try
+ {
+ await db.Database.EnsureCreatedAsync();
+ app.Logger.LogInformation("Integrations database schema ensured");
+ }
+ catch (Exception ex)
+ {
+ app.Logger.LogWarning(ex, "Integrations database EnsureCreated failed (may already exist)");
+ }
+}
+
// Configure pipeline
if (app.Environment.IsDevelopment())
{
diff --git a/src/Notify/__Libraries/StellaOps.Notify.Persistence/Extensions/NotifyPersistenceExtensions.cs b/src/Notify/__Libraries/StellaOps.Notify.Persistence/Extensions/NotifyPersistenceExtensions.cs
index 6d5d154aa..19cb80e55 100644
--- a/src/Notify/__Libraries/StellaOps.Notify.Persistence/Extensions/NotifyPersistenceExtensions.cs
+++ b/src/Notify/__Libraries/StellaOps.Notify.Persistence/Extensions/NotifyPersistenceExtensions.cs
@@ -1,5 +1,6 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
+using StellaOps.Infrastructure.Postgres.Migrations;
using StellaOps.Infrastructure.Postgres.Options;
using StellaOps.Notify.Persistence.Postgres;
using StellaOps.Notify.Persistence.Postgres.Repositories;
@@ -26,6 +27,12 @@ public static class NotifyPersistenceExtensions
services.Configure(configuration.GetSection(sectionName));
services.AddSingleton();
+ // Auto-migrate notify schema on startup
+ services.AddStartupMigrations(
+ schemaName: "notify",
+ moduleName: "Notify",
+ migrationsAssembly: typeof(NotifyDataSource).Assembly);
+
// Register repositories
services.AddScoped();
services.AddScoped();
diff --git a/src/Platform/StellaOps.Platform.WebService/Program.cs b/src/Platform/StellaOps.Platform.WebService/Program.cs
index 8f0364130..33371df2b 100644
--- a/src/Platform/StellaOps.Platform.WebService/Program.cs
+++ b/src/Platform/StellaOps.Platform.WebService/Program.cs
@@ -2,6 +2,7 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using StellaOps.Auth.ServerIntegration;
+using StellaOps.Infrastructure.Postgres.Migrations;
using StellaOps.Auth.ServerIntegration.Tenancy;
using StellaOps.Configuration;
using StellaOps.Localization;
@@ -226,6 +227,13 @@ if (!string.IsNullOrWhiteSpace(bootstrapOptions.Storage.PostgresConnectionString
builder.Services.AddSingleton();
builder.Services.AddSingleton();
builder.Services.AddSingleton();
+
+ // Auto-migrate platform schemas on startup (release, platform, analytics, shared)
+ builder.Services.AddStartupMigrations(
+ schemaName: "release",
+ moduleName: "Platform.Release",
+ typeof(StellaOps.Platform.Database.MigrationModuleRegistry).Assembly,
+ options => options.Storage.PostgresConnectionString!);
}
else
{