qa iteration 2
This commit is contained in:
14
AGENTS.md
14
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
|
- If compatibility is unclear, mark the sprint task `BLOCKED` and record the
|
||||||
risk in `Decisions & Risks`.
|
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`: `<EmbeddedResource Include="Migrations\**\*.sql" />`).
|
||||||
|
- 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:
|
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.
|
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.
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ These checklists are mandatory. Pick the relevant checklist(s) and satisfy them.
|
|||||||
- [ ] Indexing considered for new query patterns.
|
- [ ] Indexing considered for new query patterns.
|
||||||
- [ ] Serialization round-trip tests updated/added.
|
- [ ] Serialization round-trip tests updated/added.
|
||||||
- [ ] Roll-forward behavior documented; rollback constraints noted.
|
- [ ] 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
|
### 4.5 Security-sensitive change
|
||||||
- [ ] Threat note added in sprint "Decisions & Risks" (what can go wrong + mitigation).
|
- [ ] Threat note added in sprint "Decisions & Risks" (what can go wrong + mitigation).
|
||||||
|
|||||||
@@ -96,6 +96,21 @@ builder.TryAddStellaOpsLocalBinding("integrations");
|
|||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
app.LogStellaOpsLocalHostname("integrations");
|
app.LogStellaOpsLocalHostname("integrations");
|
||||||
|
|
||||||
|
// Auto-migrate: ensure integrations schema and tables exist on startup
|
||||||
|
using (var scope = app.Services.CreateScope())
|
||||||
|
{
|
||||||
|
var db = scope.ServiceProvider.GetRequiredService<IntegrationDbContext>();
|
||||||
|
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
|
// Configure pipeline
|
||||||
if (app.Environment.IsDevelopment())
|
if (app.Environment.IsDevelopment())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using StellaOps.Infrastructure.Postgres.Migrations;
|
||||||
using StellaOps.Infrastructure.Postgres.Options;
|
using StellaOps.Infrastructure.Postgres.Options;
|
||||||
using StellaOps.Notify.Persistence.Postgres;
|
using StellaOps.Notify.Persistence.Postgres;
|
||||||
using StellaOps.Notify.Persistence.Postgres.Repositories;
|
using StellaOps.Notify.Persistence.Postgres.Repositories;
|
||||||
@@ -26,6 +27,12 @@ public static class NotifyPersistenceExtensions
|
|||||||
services.Configure<PostgresOptions>(configuration.GetSection(sectionName));
|
services.Configure<PostgresOptions>(configuration.GetSection(sectionName));
|
||||||
services.AddSingleton<NotifyDataSource>();
|
services.AddSingleton<NotifyDataSource>();
|
||||||
|
|
||||||
|
// Auto-migrate notify schema on startup
|
||||||
|
services.AddStartupMigrations(
|
||||||
|
schemaName: "notify",
|
||||||
|
moduleName: "Notify",
|
||||||
|
migrationsAssembly: typeof(NotifyDataSource).Assembly);
|
||||||
|
|
||||||
// Register repositories
|
// Register repositories
|
||||||
services.AddScoped<IChannelRepository, ChannelRepository>();
|
services.AddScoped<IChannelRepository, ChannelRepository>();
|
||||||
services.AddScoped<IDeliveryRepository, DeliveryRepository>();
|
services.AddScoped<IDeliveryRepository, DeliveryRepository>();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using StellaOps.Auth.ServerIntegration;
|
using StellaOps.Auth.ServerIntegration;
|
||||||
|
using StellaOps.Infrastructure.Postgres.Migrations;
|
||||||
using StellaOps.Auth.ServerIntegration.Tenancy;
|
using StellaOps.Auth.ServerIntegration.Tenancy;
|
||||||
using StellaOps.Configuration;
|
using StellaOps.Configuration;
|
||||||
using StellaOps.Localization;
|
using StellaOps.Localization;
|
||||||
@@ -226,6 +227,13 @@ if (!string.IsNullOrWhiteSpace(bootstrapOptions.Storage.PostgresConnectionString
|
|||||||
builder.Services.AddSingleton<IAdministrationTrustSigningStore, PostgresAdministrationTrustSigningStore>();
|
builder.Services.AddSingleton<IAdministrationTrustSigningStore, PostgresAdministrationTrustSigningStore>();
|
||||||
builder.Services.AddSingleton<IPlatformContextStore, PostgresPlatformContextStore>();
|
builder.Services.AddSingleton<IPlatformContextStore, PostgresPlatformContextStore>();
|
||||||
builder.Services.AddSingleton<ITranslationStore, PostgresTranslationStore>();
|
builder.Services.AddSingleton<ITranslationStore, PostgresTranslationStore>();
|
||||||
|
|
||||||
|
// Auto-migrate platform schemas on startup (release, platform, analytics, shared)
|
||||||
|
builder.Services.AddStartupMigrations<PlatformServiceOptions>(
|
||||||
|
schemaName: "release",
|
||||||
|
moduleName: "Platform.Release",
|
||||||
|
typeof(StellaOps.Platform.Database.MigrationModuleRegistry).Assembly,
|
||||||
|
options => options.Storage.PostgresConnectionString!);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user