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 {