Scaffold the Before-M1 repo skeleton

Stand up the modular-monolith skeleton per docs/V1_BUILD_PLAN.md: one .NET 10
solution with web + worker hosts sharing seven interface-bounded module projects,
PostgreSQL 17 + pgvector via EF Core 10, a React 19 + Vite SPA built into wwwroot,
and Docker Compose for one-command local dev. Skeleton only — no feature code.

Architecture
- One project per module (OrgBoard, Identity, Skills, Assembler, Governance,
  Memory, Integrations); each is its own assembly so non-public types (entities,
  DbContext) are invisible across modules at compile time.
- TeamUp.Bootstrap is the only library that references all modules; both hosts
  reference only Bootstrap. SharedKernel/Infrastructure never reference modules.
- IModule seam: Register(...) runs in both hosts; MapEndpoints(...) only in web.
- PlatformDbContext owns the pgvector extension + the seven module schemas
  (InitialPlatform migration); MigrationRunner applies it then any module context.
- One image, two roles selected by RUN_MODE at the Docker entrypoint.

Verified
- dotnet build green (nullable + warnings-as-errors).
- ArchitectureTests 8/8 — reflection-based boundary rules (no module -> module,
  -> Infrastructure, -> Bootstrap, or -> host references).
- IntegrationTests 10/10 — Testcontainers boots the host against real pgvector:
  migration applies, vector extension + 7 schemas exist, /health 200, every
  /api/<module>/ping 200, /openapi/v1.json served.
- client builds clean (Vite 6 — pinned for Node 22.3.0; Vite 8 needs Node >=22.12).

Packages and base images route through the Nexus mirror (mirror.soroushasadi.com),
reachable from Iran when nuget.org / Docker Hub / MCR are not. CI is intentionally
deferred to a later session.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-09 06:41:28 +03:30
commit 36fe158b43
89 changed files with 7329 additions and 0 deletions
+56
View File
@@ -0,0 +1,56 @@
using OpenTelemetry.Trace;
using Serilog;
using TeamUp.Bootstrap;
using TeamUp.Infrastructure.Observability;
using TeamUp.Infrastructure.Persistence;
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog((context, services, configuration) => configuration
.ReadFrom.Configuration(context.Configuration)
.ReadFrom.Services(services));
builder.Services.AddOpenApi();
builder.Services.AddTeamUpObservability(
builder.Configuration,
serviceName: "teamup-web",
configureTracing: tracing => tracing.AddAspNetCoreInstrumentation());
builder.Services.AddTeamUpPersistence(builder.Configuration);
builder.Services.AddTeamUpModules(builder.Configuration);
var app = builder.Build();
// Apply migrations on startup when configured (default: in Development). EF Core takes a
// DB-wide lock, so the web and worker applying concurrently is safe.
if (app.Configuration.GetValue("Database:ApplyMigrationsOnStartup", app.Environment.IsDevelopment()))
{
await MigrationRunner.MigrateAllAsync(app.Services);
}
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
app.UseSerilogRequestLogging();
// Serve the built SPA from wwwroot (single deployable). UseStaticFiles (not MapStaticAssets)
// because the SPA is copied into wwwroot at publish/Docker time, after the build-time asset
// manifest is computed.
app.UseDefaultFiles();
app.UseStaticFiles();
app.MapHealthChecks("/health");
app.MapTeamUpModules();
// SPA deep links (client-side routing) fall back to index.html.
app.MapFallbackToFile("index.html");
app.Run();
/// <summary>Exposed so the integration tests can drive the host via WebApplicationFactory.</summary>
public partial class Program
{
}