Courier MFT

Tech Stack & Key Libraries

Technologies and libraries used in Courier MFT — .NET, PostgreSQL, Next.js, and more.

This section catalogs every technology choice in Courier, organized by layer. Each entry includes the specific package, its version constraint, what it's used for, and which section(s) it supports.

3.1 Runtime & Frameworks

TechnologyVersionPurposeSection
.NET10Application runtime, API host, background servicesAll
ASP.NET Core10REST API framework, middleware pipeline, OpenAPI10, 12
Entity Framework Core10ORM for PostgreSQL (query/change tracking only — not migrations)4, 13
Npgsql.EntityFrameworkCore.PostgreSQLLatest stableEF Core PostgreSQL provider13
EFCore.NamingConventionsLatest stableAutomatic snake_case mapping for EF Core13
.NET AspireLatest stableService orchestration, health checks, telemetry14
Next.jsLatest stable (React)Frontend framework11
PostgreSQL16+Primary database13

3.2 Job Scheduling & Workflow

PackagePurposeSection
Quartz.NETCron scheduling, one-shot scheduling, persistent job store (AdoJobStore)5
Quartz.Serialization.SystemTextJsonQuartz serialization using System.Text.Json (preferred over Newtonsoft where possible)5

Quartz.NET is used solely as the scheduling trigger layer. It fires at the scheduled time and delegates to Courier's Job Engine for actual execution. Quartz tables (QRTZ_*) are managed via DbUp (Section 13.3.6).

3.3 File Transfer

PackagePurposeSection
SSH.NETSFTP client — connections, uploads, downloads, directory operations, host key verification6
FluentFTPFTP/FTPS client — connections, uploads, downloads, TLS negotiation, passive mode6

Both libraries are wrapped behind the ITransferClient abstraction (Section 6.2). Application code never references SSH.NET or FluentFTP types directly outside the protocol adapter implementations.

3.4 Cryptography & Key Management

PackagePurposeSection
BouncyCastle (Portable.BouncyCastle)PGP operations — encrypt, decrypt, sign, verify, key generation, key import/export, armor encoding, keyring parsing7
System.Security.Cryptography (.NET)AES-256-GCM encryption at rest, RSA/ECDSA key generation, SHA-256/384/512 hashing, CSPRNG7, 12
Azure.Security.KeyVault.KeysMaster key (KEK) management — wrap/unwrap DEKs7, 12
Azure.Security.KeyVault.SecretsApplication secrets (connection strings, Entra client secret)12
Azure.IdentityDefaultAzureCredential for Key Vault authentication (Managed Identity in prod, Azure CLI in dev)12

FIPS note: When FIPS mode is enabled, internal cryptographic operations use .NET's System.Security.Cryptography APIs (backed by CNG on Windows, OpenSSL on Linux) restricted to FIPS-approved algorithms. Whether the underlying module runs in its FIPS-validated mode depends on OS/container configuration (Section 12.10). BouncyCastle (standard edition) is restricted to approved algorithms but is not a FIPS-validated module; a migration path to bcpg-fips-csharp exists if validated PGP operations are required.

3.5 Compression

PackagePurposeSection
SharpZipLibZIP (with AES-256 password support), GZIP, TAR, TAR.GZ — compress and decompress8
SharpCompressRAR decompression only (RAR creation is proprietary)8
7z CLI (system dependency)7z format — compress and decompress via Process wrapper8

All compression operations use streaming APIs and never load full files into memory. The ICompressionProvider abstraction (Section 8.1) wraps each library.

3.6 Authentication & Authorization

PackagePurposeSection
Microsoft.Identity.WebEntra ID JWT bearer token validation, OIDC metadata, token claim extraction12
Microsoft.AspNetCore.Authentication.JwtBearerASP.NET JWT authentication middleware12

Roles (Admin, Operator, Viewer) are defined as Entra ID App Roles and enforced via [Authorize(Roles = "...")] attributes (Section 12.2).

3.7 API & Validation

PackagePurposeSection
Swashbuckle.AspNetCoreOpenAPI/Swagger spec generation, Swagger UI (dev/staging only)10
FluentValidationRequest body validation with auto-discovery10
FluentValidation.AspNetCoreASP.NET Core integration (validation filter)10

3.8 Database & Migrations

PackagePurposeSection
DbUpDatabase migration runner — numbered SQL scripts, embedded resources, executed on API startup only (Section 13.1)13
DbUp.PostgreSQLPostgreSQL provider for DbUp13
NpgsqlLow-level PostgreSQL driver (used by EF Core and DbUp)13

Migrations are raw SQL scripts managed via DbUp. EF Core is not used for migrations — it is used only for querying and change tracking against the schema that DbUp creates.

3.9 JSON Serialization

PackagePurposeSection
System.Text.JsonPrimary serializer — API requests/responses, JSONB columns, configurationAll
Newtonsoft.JsonRequired by Quartz.NET AdoJobStore serialization; used nowhere else5

Configuration:

builder.Services.ConfigureHttpJsonOptions(options =>
{
    options.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
    options.SerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
    options.SerializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.SnakeCaseLower));
});

Enums are serialized as snake_case strings ("retry_step", "sftp") rather than integers, for API readability. JSONB columns in PostgreSQL use the same serializer settings via EF Core's HasConversion or Npgsql's ConfigureJsonOptions.

3.10 Logging & Observability

PackagePurposeSection
SerilogStructured logging framework12
Serilog.Sinks.ConsoleConsole output (all environments)
Serilog.Sinks.SeqSeq sink for development — rich local log search and dashboards
Serilog.Sinks.ApplicationInsightsAzure Application Insights sink for staging/production
Serilog.Enrichers.EnvironmentMachine name, process ID enrichment
Serilog.Enrichers.ThreadThread ID enrichment
Serilog.AspNetCoreASP.NET Core request logging integration

Configuration:

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
    .MinimumLevel.Override("System", LogEventLevel.Warning)
    .MinimumLevel.Override("Quartz", LogEventLevel.Warning)
    .Enrich.FromLogContext()
    .Enrich.WithMachineName()
    .Enrich.WithThreadId()
    .WriteTo.Console(outputTemplate:
        "[{Timestamp:HH:mm:ss} {Level:u3}] {SourceContext} {Message:lj}{NewLine}{Exception}")
    .WriteTo.Conditional(
        _ => builder.Environment.IsDevelopment(),
        config => config.Seq("http://localhost:5341"))
    .WriteTo.Conditional(
        _ => !builder.Environment.IsDevelopment(),
        config => config.ApplicationInsights(
            builder.Configuration["ApplicationInsights:ConnectionString"],
            TelemetryConverter.Traces))
    .CreateLogger();

Sensitive data redaction: Serilog destructuring policies are configured to redact passwords, passphrases, private key material, and bearer tokens from all log output (Section 12.8).

3.11 Testing

PackagePurpose
xUnitTest framework — test discovery, execution, parallelization
ShouldlyAssertion library — fluent, readable assertions with rich failure messages
NSubstituteMocking library — substitute interfaces and verify interactions
Microsoft.AspNetCore.Mvc.TestingIntegration test host — in-memory API server for endpoint testing
Testcontainers.PostgreSqlDisposable PostgreSQL containers for database integration tests
BogusFake data generation for test fixtures

Test project structure:

Courier.Tests.Unit/          Unit tests — pure logic, all dependencies mocked
Courier.Tests.Integration/   Integration tests — real database (Testcontainers), real HTTP
Courier.Tests.Architecture/  Architecture tests — enforce dependency rules, naming conventions

3.12 Infrastructure & Deployment

TechnologyPurposeSection
DockerContainerization — multi-stage builds for API and background services14
Kubernetes / Azure Container AppsContainer orchestration (deployment target)14
.NET AspireLocal development orchestration, service discovery, health checks14
Azure Database for PostgreSQL Flexible ServerManaged PostgreSQL with TDE, automated backups13, 14
Azure Key VaultMaster key storage (FIPS 140-2 Level 2/3), application secrets7, 12
Azure Application InsightsProduction telemetry, distributed tracing, alerting
Azure Blob StorageCold storage for archived partition data13

3.13 Package Version Policy

Version constraints:

  • .NET 10 and ASP.NET Core 10: Pinned to the major version. Minor/patch updates applied via regular dependency updates.
  • EF Core: Matches the .NET major version (EF Core 10 with .NET 10).
  • All NuGet packages: Use the latest stable release at project initialization. Pinned to major version with ~> range to allow patch updates. Breaking changes require an explicit upgrade decision.
  • PostgreSQL: Minimum version 16 for native partitioning performance improvements and JSONB enhancements.

Dependency audit: dotnet list package --vulnerable is run as part of the CI pipeline. Packages with known CVEs are flagged as build warnings (high severity) or build failures (critical severity).

3.14 Library Decision Summary

┌──────────────────┬──────────────────────────────────────────────┐
│ Concern           │ Decision                                     │
├──────────────────┼──────────────────────────────────────────────┤
│ Runtime           │ .NET 10                                      │
│ Frontend          │ Next.js (React)                              │
│ Database          │ PostgreSQL 16+                               │
│ ORM               │ EF Core 10 (query only, not migrations)     │
│ Migrations        │ DbUp (raw SQL scripts)                      │
│ Scheduling        │ Quartz.NET (AdoJobStore)                    │
│ SFTP              │ SSH.NET                                      │
│ FTP/FTPS          │ FluentFTP                                    │
│ PGP               │ BouncyCastle (FIPS-approved algorithms only) │
│ Encryption        │ .NET System.Security.Cryptography (CNG/OSSL) │
│ Key management    │ Azure Key Vault                              │
│ Compression       │ SharpZipLib + SharpCompress + 7z CLI         │
│ Auth              │ Entra ID via Microsoft.Identity.Web          │
│ API docs          │ Swashbuckle (OpenAPI/Swagger)                │
│ Validation        │ FluentValidation                             │
│ JSON (primary)    │ System.Text.Json                             │
│ JSON (Quartz)     │ Newtonsoft.Json                              │
│ Logging           │ Serilog → Seq (dev) / App Insights (prod)   │
│ Testing           │ xUnit + Shouldly + NSubstitute               │
│ Orchestration     │ .NET Aspire (dev), Docker + K8s (prod)      │
└──────────────────┴──────────────────────────────────────────────┘